Sandbox


Dave: One of the key hypotheses is that profits (mark-ups) will be less responsive in the 2p game (because of collusion). Could you compute the mean (and median) for each period for each pair (or group), i.e. average across all the rounds. For each of those periods observations we’ll have a transport cost. What I’d like to do is log that data then run a regression of ln(profit)= a0 + a1*ln(transport cost)+ (a2 * 2p) + (a3 * 2p * ln(transport cost)), where 2p is a dummy for 2p periods. I think this is the correct equation.. Essentially, I want to estimate the elasticity of profits to transport costs and see if that is higher for 4p sessions. We should expect a1 to be positive and a3 to be negative, if my hypotheses are correct…–

Above is the distribution of round profits. Where round profits is the mean profit of one subject in one period (at a fixed transport cost and number of counterparts).

However, we have a problem. Profit and transport costs are between 0 and 1. Log profit is not possible without omitting observations (introducing bias) or other manipulations.

I transform profit by adding an insignificant quantity (0.01) to all observations, and multiplying that by 10000.

This produces the following distribution of observed profits;

With this transformation to profit, we have the following regression.


Call:
lm(formula = log_profit ~ log(player.transport_cost) + twoPlayer + 
    twoPlayer:log(player.transport_cost), data = df)

Residuals:
     Min       1Q   Median       3Q      Max 
-1.50639 -0.25709 -0.04077  0.24720  1.87950 

Coefficients:
                                     Estimate Std. Error t value Pr(>|t|)    
(Intercept)                           6.44720    0.03306 194.987  < 2e-16 ***
log(player.transport_cost)            0.48422    0.02731  17.733  < 2e-16 ***
twoPlayer                             0.77865    0.05228  14.894  < 2e-16 ***
log(player.transport_cost):twoPlayer -0.23764    0.04317  -5.504 6.07e-08 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.4125 on 476 degrees of freedom
Multiple R-squared:  0.6798,    Adjusted R-squared:  0.6778 
F-statistic: 336.9 on 3 and 476 DF,  p-value: < 2.2e-16

With issues in transforming profit in mind, we have the above regression results. If we hadn’t transformed profit and been able to run a regular log-log regression with your specification, we would interpret \(\beta_3\) as “the 2-player game, a one unit increase in transport cost decreases profit by 23% compared to the 4-player game” (if my interpretation is correct).

Additional regressions:

Normalized Profit


Call:
lm(formula = stdz_profit ~ log(player.transport_cost) + twoPlayer + 
    twoPlayer:log(player.transport_cost), data = df)

Residuals:
    Min      1Q  Median      3Q     Max 
-1.6466 -0.5758 -0.1649  0.3356  4.0475 

Coefficients:
                                     Estimate Std. Error t value Pr(>|t|)    
(Intercept)                           1.97723    0.06883  28.728  < 2e-16 ***
log(player.transport_cost)            0.67358    0.05684  11.851  < 2e-16 ***
twoPlayer                             0.43323    0.10882   3.981 7.93e-05 ***
log(player.transport_cost):twoPlayer -0.28088    0.08987  -3.125  0.00188 ** 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.8587 on 476 degrees of freedom
Multiple R-squared:  0.3362,    Adjusted R-squared:  0.332 
F-statistic: 80.37 on 3 and 476 DF,  p-value: < 2.2e-16

A regression with normalized profit is statistically significant, and has similar results as the price-transformed log-log.

Now we would interpret \(\beta_3\) as “the 2-player game, a one unit increase in transport cost decreases profit by 0.23 standard deviations compared to the 4-player game” (if my interpretation is correct, that could probably be said better).

Level - Log


Call:
lm(formula = profit ~ log(player.transport_cost) + twoPlayer + 
    twoPlayer:log(player.transport_cost), data = df)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.07557 -0.02045 -0.00580  0.01095  0.19876 

Coefficients:
                                     Estimate Std. Error t value Pr(>|t|)    
(Intercept)                          0.055477   0.002952  18.793  < 2e-16 ***
log(player.transport_cost)           0.018900   0.002438   7.752 5.51e-14 ***
twoPlayer                            0.076371   0.004668  16.362  < 2e-16 ***
log(player.transport_cost):twoPlayer 0.002581   0.003855   0.670    0.503    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.03683 on 476 degrees of freedom
Multiple R-squared:  0.5493,    Adjusted R-squared:  0.5464 
F-statistic: 193.4 on 3 and 476 DF,  p-value: < 2.2e-16

A Regular level-log regression has player.transport_cost:twoPlayer is insignificant.


Dave: How did you measure collusion in your other Hotellings work? I’d like to know if “collusion” is higher in 2p sessions and, if it’s higher in low transport cost periods, in both 2p and 4p. Looking at the second figure for 2p, it looks like the profits that are much higher than the bulk of the mass (which is suggestive of collusion), and this happens more frequently at low transport costs. You see the same sort of pattern in the second figure in 4p, but more less prevalent. Visually, it seems suggestive of these additional hypotheses.–

We had a few measures of collusion. Since we had a continuous time data, we looked at how subjects responded to others’ action selection. E.g., (in the price and location Hotelling setting), when a player did change their action, did they move location and price in a way that opened up the possibility of getting higher joint profit (which usually meant reducing one’s profit)? Or did they act “competitively”, increasing own profit at expense of counterparty? As another measure of collusion, if there were joint positive profits, did players remain stationary?

Collusion Metrics:

  • In this setting, we might consider the direct and magnitude of price changes. Where changes in prices generally down? or up? This has problems since players colliding at very high prices don’t have room to signal further collusion by increasing prices.
  • … I don’t have a good response to this…

Regarding your observation that looking at profit and transport costs, the very low transport cost treatments had lower than average profit, but had a few observations with very high profit. Isn’t this more a “technical artifact” (probably not the right term…), where with t = 0.1 if your opponent has high prices, a slightly lower price will seriously undercut them and capture a large portion of the market. Whereas with high transport cost, you need to be seriously below your opponent to undercut their price and capture serious market share. So, it would seem to me that there are a few cases with low transport costs where a “good” player was up against a careless one, and in that period the good player earned the rare, very high profit that period.

Two-Player Game

Sessions run so far,

session.code n_subjects date
e6zctbfm 10 2017-02-08 19:52:36.968156+00:00
vtfqykgg 6 2017-02-09 19:46:26.598872+00:00

Profit and Transport Costs

A fairly clear story here. The figure below plots average payoffs for each session. This averages payoffs over all subject in all periods within one session.

Note that the transport cost of 0.25 had an error in its implementation. In 0.25 transport cost periods, subjects only had 5 subperiods, not the 20 all other periods had. This most likely explains the odd result.

In the table below I compare average payoff between transport cost treatments, at the session level.

The standard errors are probably not the way you want to do it. I’m using every observation from each subperiod of each period. We probably want to compare average payoffs per period or per session. But still…

player.transport_cost n mean_profit median_profit se_profit
0.10 960 0.0875815 0.0350000 0.0036772
0.25 240 0.0981567 0.0799500 0.0064890
0.50 960 0.0986849 0.0900000 0.0022796
0.75 960 0.1281301 0.1170667 0.0023177
1.00 960 0.1424673 0.1353250 0.0020214

Now, below, we calculate standard error with mean payoffs at the session+period+transport cost level.

There are far fewer observations, making our standard error much larger. However, still, the very low transport cost are significantly different from the two transport costs in the high range.

player.transport_cost n mean_profit_ se_profit
0.10 6 0.0945531 0.0133701
0.25 6 0.0999280 0.0085969
0.50 6 0.1023566 0.0094255
0.75 6 0.1298086 0.0068505
1.00 6 0.1472174 0.0103132

Looking at distributions in another way,

Below, we have the distribution of all subperiod/round profits. Within each transport costs group, colors represent a single period. We see remarkably consistent distributions of profit within transport-cost groups, and noticeably different distributions between transport cost groups.

Now, we see the distribution of profits over each transport costs, averaged over a given session+period (less granular than above).

To summarize a little:

  • The lower the transport cost the lower the profit to the subject.

  • There is a clear and likely statistically significant difference between average payoffs (our proxy for cooperation rates) between low transport cost t = 0.1 and high t = 1.0.

  • The difference between t = 1.0 and t = 0.75 does not yet appear to be significant.

Period Effect

There does not appear to be any period effect. I suspected that perhaps in later periods we’d see consistently lower or higher levels of cooperations/payoffs. That does not appear to be the case

Prices and Transport Costs

How do prices related to transport cost? How does price stickiness related to transport cost?

The figure below plots prices for each session. This averages payoffs over all subject in all periods within one transport cost treatment group.

  • The violen shows the distribution of prices within that transport cost treatment group.
  • The grey ribben shows the first and third quartile of prices, that is, 50% of all prices selected by subjects in the treatment group were within the ribbin.
  • The line shows the median for each transport cost treatment group.

We see a generally positive relationship between prices and transport costs.

Note that the transport cost of 0.25 had an error in its implementation. In 0.25 transport cost periods, subjects only had 5 subperiods, not the 20 all other periods had. This most likely explains the odd result.

In the table below I compare average price between transport cost treatments, at the session level.

The standard errors are probably not the way you want to do it. I’m using every observation from each subperiod of each period. We probably want to compare average payoffs per period or per session. But still…

player.transport_cost n mean_price median_price se_price
0.10 960 0.4487188 0.405 0.0098613
0.25 240 0.4959167 0.470 0.0176038
0.50 960 0.4615833 0.420 0.0076664
0.75 960 0.5660937 0.520 0.0081746
1.00 960 0.6249167 0.590 0.0079651

Prices in the t = 1.0 transport cost treatment were on average \(0.1761979\) or \(39.15\)% higher compared to t = 0.1.

Now, below, we calculate standard error with mean prices at the session+period+transport cost level.

There are far fewer observations, making our standard error much larger. However, still, the very low transport cost are significantly different from the two transport costs in the high range.

player.transport_cost n se_price mean_price
0.10 6 0.0525694 0.4757694
0.25 6 0.0329879 0.5058000
0.50 6 0.0402877 0.4771778
0.75 6 0.0205684 0.5723750
1.00 6 0.0369182 0.6425889

Comparing prices in t = 0.1 and t = 1.0 (see below), there appears to be a statistically significant difference.

  • A t test comparing prices between min and max transport costs. Prices are average price at the session, participant, and period level. P-value 0.000029.
  • A MW rank sum test comparing prices between min and max transport costs. Prices are average price at the session, participant, and period level. P-value 0.0002061.

    Welch Two Sample t-test

data:  mean_price[player.transport_cost == 0.1] and mean_price[player.transport_cost == 1]
t = -4.4084, df = 88.447, p-value = 2.918e-05
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -0.25562210 -0.09677373
sample estimates:
mean of x mean of y 
0.4487187 0.6249167 
cannot compute exact p-value with ties

    Wilcoxon rank sum test with continuity correction

data:  mean_price[player.transport_cost == 0.1] and mean_price[player.transport_cost == 1]
W = 645, p-value = 0.0002061
alternative hypothesis: true location shift is not equal to 0

Summary of relationship between transport costs and prices. There is a relationship between prices and transport cost treatments. In higher transport cost settings subjects tended to have higher prices.

Price Stickiness and Transport Costs

Considering price stickiness as:

  • standard deviation of prices.
  • average change in price when prices were changed.
  • at the session, round, player level, average number of times player changes prices between rounds.

Looking at the standard deviation of prices (below), there does not appear to be a strong relationship between price variation and transport cost.

Below, we look at the magnitutde of changes in price between subperiods. One dot represents the average price change (in absolute value) for one player, in one period. There does not appear to be a significant relationship between this measure of price stickiness and transport cost treatment.

Below, we see the percent of times subjects change price between subperiods. As a reminder, each period is divided into a number of subperiods. If a subject does nothing with his or her experiment controls between subperiods, prices remain unchanged. Subjects must actively click to change prices between subperiods.

The percent plotted below indicated the percent of times subjects change their price between periods. A score of zero indicated the subject never changed prices. A score of 100% indicates that person changes prices between every subperiod.

Again, we see weak evidence that prices are slightly more sticky in high transport cost settings.


Four-Player Game

Profit and Transport Cost

Keep in mind, where the max score one could earn in the two-player game is 0.5 (if both players go to the Pareto superior equilibrium, or in the unlikely event that one player is at the max price and the other undercuts him at price = 0.5), in the four player game the max score one could get, I think, is 0.25. This price occurs were all players have the highest price possible.

It is possible that some players do earn above 0.25 if, in the unlikely event that they manage to undercut other players for many subperiods in the very-low transport cost world.

How player profits relate to transport cost at the very high, session level?

A very clear story, I think. The figure below plots average payoffs for each session. This averages payoffs over all subject in all periods within one session.

player.transport_cost n mean_profit median_profit se_profit
0.10 1440 0.0129521 0.0060 0.0007968
0.25 1440 0.0244524 0.0170 0.0010780
0.50 1440 0.0388499 0.0315 0.0011586
0.75 1440 0.0505971 0.0462 0.0011680
1.00 1440 0.0574560 0.0540 0.0011470

The standard errors in the table above are likely way too generous. Below, the same table, but only averaging over subject+period+transport-cost.

If things hold up, we’d get a statistically significant difference between 0.1 and 1.0, and possibly between smaller increments of transport cost.

player.transport_cost n mean_profit_ se_profit
0.10 6 0.0129521 0.0023800
0.25 6 0.0244524 0.0027642
0.50 6 0.0388499 0.0032211
0.75 6 0.0505971 0.0035959
1.00 6 0.0574560 0.0046760

Now, looking at the very granular subject, period level,

Looking more closely at the distributions, (below) we see;

  • basically, the t = 0.1 was profitless for subjects.

  • the t = 0.25 world was pretty close to unprofitable.

  • the t = 0.75 and t = 1.0 worlds were consistently in the profitable range.

The distributions here are derived from a player’s final score in the period.

Below, looking at these distrubtions with a more grandular view. Here we look at all observations of all payoffs, including those within a period.

It more clearly shows that in all of these worlds, people do spend a lot of time at zero payoffs.

I drop t = 0.1 because they are basically all at zero payoffs.

Prices and Transport Costs

How do prices related to transport cost? How does price stickiness related to transport cost?

The figure below plots prices for each session. This averages payoffs over all subject in all periods within one transport cost treatment group.

  • The violen shows the distribution of prices within that transport cost treatment group.
  • The grey ribben shows the first and third quartile of prices, that is, 50% of all prices selected by subjects in the treatment group were within the ribbin.
  • The line shows the median for each transport cost treatment group.

We see a generally positive relationship between prices and transport costs.

In the table below I compare average price between transport cost treatments, at the session level.

The standard errors are probably not the way you want to do it. I’m using every observation from each subperiod of each period. We probably want to compare average payoffs per period or per session. But still…

player.transport_cost n mean_price median_price se_price
0.10 1440 0.1705972 0.05 0.0068340
0.25 1440 0.1815278 0.10 0.0055909
0.50 1440 0.2400764 0.19 0.0050648
0.75 1440 0.2859444 0.26 0.0046222
1.00 1440 0.3164861 0.30 0.0049007

Prices in the t = 1.0 transport cost treatment were on average \(0.146\) or \(85.82\)% higher compared to t = 0.1.

Now, below, we calculate standard error with mean prices at the session+period+transport cost level.

There are far fewer observations, making our standard error much larger. However, still, the very low transport cost are significantly different from the two transport costs in the high range.

player.transport_cost n se_price mean_price
0.10 6 0.0249646 0.1705972
0.25 6 0.0266817 0.1815278
0.50 6 0.0232037 0.2400764
0.75 6 0.0236542 0.2859444
1.00 6 0.0272160 0.3164861

Comparing prices in t = 0.1 and t = 1.0 (see below), there appears to be a statistically significant difference.

  • A t test comparing prices between min and max transport costs. Prices are average price at the session, participant, and period level. P-value 0.0000002285.
  • A MW rank sum test comparing prices between min and max transport costs. Prices are average price at the session, participant, and period level. P-value 4.458e-10.

    Welch Two Sample t-test

data:  mean_price[player.transport_cost == 0.1] and mean_price[player.transport_cost == 1]
t = -5.4696, df = 127.71, p-value = 2.285e-07
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -0.19866656 -0.09311122
sample estimates:
mean of x mean of y 
0.1705972 0.3164861 


    Wilcoxon rank sum test with continuity correction

data:  mean_price[player.transport_cost == 0.1] and mean_price[player.transport_cost == 1]
W = 1030.5, p-value = 4.458e-10
alternative hypothesis: true location shift is not equal to 0

Summary of relationship between transport costs and prices. There is a relationship between prices and transport cost treatments. In higher transport cost settings subjects tended to have higher prices.

Price Stickiness and Transport Costs

Considering price stickiness as:

  • standard deviation of prices.
  • average change in price when prices were changed.
  • at the session, round, player level, average number of times player changes prices between rounds.

Looking at the standard deviation of prices (below), there does not appear to be a strong relationship between price variation and transport cost.

Below, we look at the magnitutde of changes in price between subperiods. One dot represents the average price change (in absolute value) for one player, in one period. There does not appear to be a significant relationship between this measure of price stickiness and transport cost treatment.

Below, we see the percent of times subjects change price between subperiods. As a reminder, each period is divided into a number of subperiods. If a subject does nothing with his or her experiment controls between subperiods, prices remain unchanged. Subjects must actively click to change prices between subperiods.

The percent plotted below indicated the percent of times subjects change their price between periods. A score of zero indicated the subject never changed prices. A score of \(100\)% indicates that person changes prices between every subperiod.

Again, we see weak evidence that prices are slightly more sticky in high transport cost settings.


Period Effect

The period affect, if present, is dominated by transport costs all being the same at certain periods.

Comparing the two-player game to four-player

First off note that in the two-player game, the most you can possible earn is 0.5. In the four-player game if all players set prices at their max they would each earn 0.25.


Dave: These results look great. So, it looks like we have pretty robust results for one of our hypotheses (transport costs and profits (mark-ups) from these pilots. The other questions are mostly to do with how the results change for the 2p vs. 4p games. If it’s relatively easy, could you generate those same plots, but where you stack the 2p and 4p images on top of each other so it’s easier to visually compare? Right now I’m trying to scroll back and forth to compare and it’s not working too well! –

Period Profit and Transport Cost

Price Standard Deviation and Transport Cost

Price Stickiness

Dave: On price stickiness. I was thinking more along the lines of “price responsiveness” I suppose. i.e. that price are less responsive to shocks (changes in transport costs) in the 2p sessions. We could run the same regression above, but with price, but I think we should get the same result, since profit essentially equals price here (not exactly, of course). This is related to price stickiness because if prices are less responsive, for whatever reason, monetary policy will have a greater impact. I guess I’m less interested in the within round movements in price, I just sort of view that as experimentation. One thing that I think may be interesting is to look at how price changes change as rounds go on. i.e. do the changes become less extreme later in a period and does this vary across transport costs. Again, the metrics on price stickiness you create and think are interesting, but could you do them for a 2p vs. 4p comparison? I think that comparison is much more interesting. I think we should keep the transport cost ones, but I’d also like to add the 2p vs. 4p comparison.


Call:
lm(formula = log(price) ~ log(player.transport_cost) + twoPlayer + 
    twoPlayer:log(player.transport_cost), data = df)

Residuals:
     Min       1Q   Median       3Q      Max 
-1.77125 -0.28878 -0.02919  0.30142  2.04784 

Coefficients:
                                     Estimate Std. Error t value Pr(>|t|)    
(Intercept)                          -1.22448    0.04226 -28.977  < 2e-16 ***
log(player.transport_cost)            0.44403    0.03490  12.724  < 2e-16 ***
twoPlayer                             0.64726    0.06681   9.687  < 2e-16 ***
log(player.transport_cost):twoPlayer -0.27135    0.05518  -4.918 1.21e-06 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.5272 on 476 degrees of freedom
Multiple R-squared:  0.5082,    Adjusted R-squared:  0.5051 
F-statistic:   164 on 3 and 476 DF,  p-value: < 2.2e-16

Similar results to log-log with profit and transport costs.

And with normalized price,


Call:
lm(formula = stdz_price ~ log(player.transport_cost) + twoPlayer + 
    twoPlayer:log(player.transport_cost), data = df)

Residuals:
    Min      1Q  Median      3Q     Max 
-1.8119 -0.6860 -0.2355  0.4110  4.2781 

Coefficients:
                                     Estimate Std. Error t value Pr(>|t|)    
(Intercept)                           1.97554    0.07580  26.063  < 2e-16 ***
log(player.transport_cost)            0.39169    0.06260   6.257 8.74e-10 ***
twoPlayer                             0.98848    0.11985   8.248 1.59e-15 ***
log(player.transport_cost):twoPlayer -0.05464    0.09898  -0.552    0.581    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.9457 on 476 degrees of freedom
Multiple R-squared:  0.2917,    Adjusted R-squared:  0.2872 
F-statistic: 65.34 on 3 and 476 DF,  p-value: < 2.2e-16

The results is now insignificant.


Sustained joint profits.

As a measure or indication of collusion, here we use the situation in which both players have profitable positions.

There are other explainations for both players having positive profits where they are not colluding. For example, if they are attempting to undercut their competitor but accidentially allow them a profit. High transport costs also limit the ability for competitors to undercut others.

The following table shows the percent of the subperiod in which all players had at positive payoffs. We see a clear relationship between transport cost and firms ability to maintain joint positive profits.

Below, I am curious how payoffs evolved as periods progressed. Were they stable, or did they tend to decline?

The plots below show the distributions of payoffs over the period. The x-axis is the subperiod, the y-axis the flow payoff.

There are jittered poits and violins to show distributions. The line shows the median over all observations in this group.

It’s hard to see, but in the two-player game, the distributions of profits are remarkably consistent between subperiods in t = 0.5, 0.75 and 1.0.

Distribution of price changes.

One indication of collusion is stable actions.


This is an R Markdown Notebook. When you execute code within the notebook, the results appear beneath the code.

LS0tCnRpdGxlOiAiSG90ZWxsaW5nIE1hcmt1cHMgSW5pdGlhbCBBbmFseXNpcyIKYXV0aG9yOiAiQ3VydGlzIEtlcGhhcnQiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogMgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiAyCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGVjaG8gPSBGQUxTRSwgZXJyb3I9RkFMU0UsIGluY2x1ZGU9RkFMU0UsIGNhY2hlPUZBTFNFfQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoa25pdHIpCmxpYnJhcnkodGlkeXIpCnNvdXJjZSgiZXRsLnIiKQpgYGAKCgoKIyMgU2FuZGJveAoKCi0tLS0tCgotLSoqRGF2ZSoqOiBPbmUgb2YgdGhlIGtleSBoeXBvdGhlc2VzIGlzIHRoYXQgcHJvZml0cyAobWFyay11cHMpIHdpbGwgYmUgbGVzcyByZXNwb25zaXZlIGluIHRoZSAycCBnYW1lIChiZWNhdXNlIG9mIGNvbGx1c2lvbikuIENvdWxkIHlvdSBjb21wdXRlIHRoZSBtZWFuIChhbmQgbWVkaWFuKSBmb3IgZWFjaCBwZXJpb2QgZm9yIGVhY2ggcGFpciAob3IgZ3JvdXApLCBpLmUuIGF2ZXJhZ2UgYWNyb3NzIGFsbCB0aGUgcm91bmRzLiBGb3IgZWFjaCBvZiB0aG9zZSBwZXJpb2RzIG9ic2VydmF0aW9ucyB3ZSdsbCBoYXZlIGEgdHJhbnNwb3J0IGNvc3QuIFdoYXQgSSdkIGxpa2UgdG8gZG8gaXMgbG9nIHRoYXQgZGF0YSB0aGVuIHJ1biBhIHJlZ3Jlc3Npb24gb2YgYGxuKHByb2ZpdCk9IGEwICsgYTEqbG4odHJhbnNwb3J0IGNvc3QpKyAoYTIgKiAycCkgKyAoYTMgKiAycCAqIGxuKHRyYW5zcG9ydCBjb3N0KSlgLCB3aGVyZSAycCBpcyBhIGR1bW15IGZvciAycCBwZXJpb2RzLiBJIHRoaW5rIHRoaXMgaXMgdGhlIGNvcnJlY3QgZXF1YXRpb24uLiBFc3NlbnRpYWxseSwgSSB3YW50IHRvIGVzdGltYXRlIHRoZSBlbGFzdGljaXR5IG9mIHByb2ZpdHMgdG8gdHJhbnNwb3J0IGNvc3RzIGFuZCBzZWUgaWYgdGhhdCBpcyBoaWdoZXIgZm9yIDRwIHNlc3Npb25zLiBXZSBzaG91bGQgZXhwZWN0IGExIHRvIGJlIHBvc2l0aXZlIGFuZCBhMyB0byBiZSBuZWdhdGl2ZSwgaWYgbXkgaHlwb3RoZXNlcyBhcmUgY29ycmVjdC4uLi0tCgpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGVjaG8gPSBGQUxTRSwgZXJyb3I9RkFMU0UsIGNhY2hlPUZBTFNFfQoKCmRmID0gIHNlc0RhdDJwICU+JQogIHVuZ3JvdXAoKSAlPiUKICBncm91cF9ieShzZXNzaW9uLmNvZGUsIHBhcnRpY2lwYW50LmNvZGUsIHBsYXllci50cmFuc3BvcnRfY29zdCxwbGF5ZXIucGVyaW9kX251bWJlcikgJT4lCiAgbXV0YXRlKAogICAgcGxheWVyLnJvdW5kX3BheW9mZiA9IHBsYXllci5yb3VuZF9wYXlvZmYgKiBtYXgoc3Vic2Vzc2lvbi5yb3VuZF9udW1iZXIpICNkZWFsIHdpdGggZidpbmcgdD0wLjI1Li4uCiAgKSAlPiUKICBzdW1tYXJpc2UoCiAgICBwcm9maXQgPSBtZWFuKHBsYXllci5yb3VuZF9wYXlvZmYpLAogICAgcHJvZml0X21lZGlhbiA9IG1lZGlhbihwbGF5ZXIucm91bmRfcGF5b2ZmKSwKICAgIHR3b1BsYXllciA9IDEsCiAgICBwbGF5ZXJOdW0gPSAiVHdvIFBsYXllcnMiCiAgKQoKZGYgPSBiaW5kX3Jvd3MoCiAgZGYsIAogIHNlc0RhdDRwICU+JQogICAgdW5ncm91cCgpICU+JQogICAgZ3JvdXBfYnkoc2Vzc2lvbi5jb2RlLCBwYXJ0aWNpcGFudC5jb2RlLCBwbGF5ZXIudHJhbnNwb3J0X2Nvc3QscGxheWVyLnBlcmlvZF9udW1iZXIpICU+JQogICAgbXV0YXRlKAogICAgICBwbGF5ZXIucm91bmRfcGF5b2ZmID0gcGxheWVyLnJvdW5kX3BheW9mZiAqIG1heChzdWJzZXNzaW9uLnJvdW5kX251bWJlcikgI2RlYWwgd2l0aCBmJ2luZyB0PTAuMjUuLi4KICAgICkgJT4lCiAgICBzdW1tYXJpc2UoCiAgICAgIHByb2ZpdCA9IG1lYW4ocGxheWVyLnJvdW5kX3BheW9mZiksCiAgICAgIHByb2ZpdF9tZWRpYW4gPSBtZWRpYW4ocGxheWVyLnJvdW5kX3BheW9mZiksCiAgICAgIHR3b1BsYXllciA9IDAsCiAgICAgIHBsYXllck51bSA9ICJGb3VyIFBsYXllcnMiCiAgICApCikgJT4lCiAgZHBseXI6OmZpbHRlcigKICAgIHBsYXllci50cmFuc3BvcnRfY29zdCAhPSAwLjI1CiAgKSAlPiUKICBtdXRhdGUoCiAgICBsb2dfcHJvZml0ID0gbG9nKChwcm9maXQgKyAwLjAxKSAqIDEwMDAwKSwKICAgIGxvZ19wcm9maXQgPSBpZmVsc2UobG9nX3Byb2ZpdCA8IDAsIDAsIGxvZ19wcm9maXQpCiAgKSAlPiUgCiAgZ3JvdXBfYnkocGxheWVyTnVtKSAlPiUKICBkcGx5cjo6bXV0YXRlKAogICAgc2RfcHJvZiA9IHNkKHByb2ZpdCksCiAgICBzdGR6X3Byb2ZpdCA9IHByb2ZpdCAvIHNkX3Byb2YKICApCnAxID0gZ2dwbG90KAogIGRmLAogIGFlcygKICAgIHggPSBwcm9maXQKICApCikgKwogIGdlb21faGlzdG9ncmFtKCkgKwogIHRoZW1lX2J3KCkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgUHJvZml0cyIsCiAgICB4ID0gIk1lYW4gcHJvZml0LCBTcyBpbiBvbmUgcGVyaW9kIG92ZXIgYWxsIHN1Yi1wZXJpb2RzIgogICkKcDEKYGBgCgpBYm92ZSBpcyB0aGUgZGlzdHJpYnV0aW9uIG9mIHJvdW5kIHByb2ZpdHMuIFdoZXJlIHJvdW5kIHByb2ZpdHMgaXMgdGhlIG1lYW4gcHJvZml0IG9mIG9uZSBzdWJqZWN0IGluIG9uZSBwZXJpb2QgKGF0IGEgZml4ZWQgdHJhbnNwb3J0IGNvc3QgYW5kIG51bWJlciBvZiBjb3VudGVycGFydHMpLgoKSG93ZXZlciwgd2UgaGF2ZSBhIHByb2JsZW0uIFByb2ZpdCBhbmQgdHJhbnNwb3J0IGNvc3RzIGFyZSBiZXR3ZWVuIDAgYW5kIDEuIExvZyBwcm9maXQgaXMgbm90IHBvc3NpYmxlIHdpdGhvdXQgb21pdHRpbmcgb2JzZXJ2YXRpb25zIChpbnRyb2R1Y2luZyBiaWFzKSBvciBvdGhlciBtYW5pcHVsYXRpb25zLgoKSSB0cmFuc2Zvcm0gcHJvZml0IGJ5IGFkZGluZyBhbiBpbnNpZ25pZmljYW50IHF1YW50aXR5ICgwLjAxKSB0byBhbGwgb2JzZXJ2YXRpb25zLCBhbmQgbXVsdGlwbHlpbmcgdGhhdCBieSAxMDAwMC4gCgpUaGlzIHByb2R1Y2VzIHRoZSBmb2xsb3dpbmcgZGlzdHJpYnV0aW9uIG9mIG9ic2VydmVkIHByb2ZpdHM7CgpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGVjaG8gPSBGQUxTRSwgZXJyb3I9RkFMU0UsIGNhY2hlPUZBTFNFfQoKcDEgPSBnZ3Bsb3QoCiAgZGYsCiAgYWVzKAogICAgeCA9IChwcm9maXQgKyAwLjAxKSAqIDEwMDAKICApCikgKwogIGdlb21faGlzdG9ncmFtKCkgKwogIHRoZW1lX2J3KCkgKwogICAgbGFicygKICAgIHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBQcm9maXRzIiwKICAgIHN1YnRpdGxlID0gIlByb2ZpdCBUcmFuc2Zvcm1hdGlvbjogYChwcm9maXQgKyAwLjAxKSAqIDEwMDAwYCIsCiAgICB4ID0gIk1lYW4gcHJvZml0LCBTcyBpbiBvbmUgcGVyaW9kIG92ZXIgYWxsIHN1Yi1wZXJpb2RzIgogICkKcDEKYGBgCgpXaXRoIHRoaXMgdHJhbnNmb3JtYXRpb24gdG8gcHJvZml0LCB3ZSBoYXZlIHRoZSBmb2xsb3dpbmcgcmVncmVzc2lvbi4gCgpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGVjaG8gPSBGQUxTRSwgZXJyb3I9RkFMU0UsIGNhY2hlPUZBTFNFfQoKCnAxPSBnZ3Bsb3QoCiAgZGYsCiAgYWVzKAogICAgeCA9IHBsYXllci50cmFuc3BvcnRfY29zdCwKICAgIHkgPSBsb2dfcHJvZml0LAogICAgZ3JvdXAgPSBwbGF5ZXJOdW0sCiAgICBjb2xvciA9IHBsYXllck51bQogICkKKSArCiAgZ2VvbV9qaXR0ZXIoCiAgICB3aWR0aCA9IDAuMDcsCiAgICBhbHBoYSA9IC40KSArCiAgZ2VvbV9zbW9vdGgoCiAgICBtZXRob2QgPSAnbG0nCiAgKSArCiAgdGhlbWVfYncoKQpwMQoKCgpyZWcgPSBsbSgKICBsb2dfcHJvZml0IH4gbG9nKHBsYXllci50cmFuc3BvcnRfY29zdCkgKyB0d29QbGF5ZXIgKyB0d29QbGF5ZXI6bG9nKHBsYXllci50cmFuc3BvcnRfY29zdCksCiAgZGYKKQoKc3VtbWFyeShyZWcpCmBgYAoKV2l0aCBpc3N1ZXMgaW4gdHJhbnNmb3JtaW5nIHByb2ZpdCBpbiBtaW5kLCB3ZSBoYXZlIHRoZSBhYm92ZSByZWdyZXNzaW9uIHJlc3VsdHMuIElmIHdlIGhhZG4ndCB0cmFuc2Zvcm1lZCBwcm9maXQgYW5kIGJlZW4gYWJsZSB0byBydW4gYSByZWd1bGFyIGxvZy1sb2cgcmVncmVzc2lvbiB3aXRoIHlvdXIgc3BlY2lmaWNhdGlvbiwgd2Ugd291bGQgaW50ZXJwcmV0ICRcYmV0YV8zJCBhcyAiKnRoZSAyLXBsYXllciBnYW1lLCBhIG9uZSB1bml0IGluY3JlYXNlIGluIHRyYW5zcG9ydCBjb3N0IGRlY3JlYXNlcyBwcm9maXQgYnkgMjMlIGNvbXBhcmVkIHRvIHRoZSA0LXBsYXllciBnYW1lKiIgKGlmIG15IGludGVycHJldGF0aW9uIGlzIGNvcnJlY3QpLiAgCgoKQWRkaXRpb25hbCByZWdyZXNzaW9uczogCgojIyMjIE5vcm1hbGl6ZWQgUHJvZml0CgpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGVjaG8gPSBGQUxTRSwgZXJyb3I9RkFMU0UsIGNhY2hlPUZBTFNFfQoKCnJlZyA9IGxtKAogIHN0ZHpfcHJvZml0fiBsb2cocGxheWVyLnRyYW5zcG9ydF9jb3N0KSArIHR3b1BsYXllciArIHR3b1BsYXllcjpsb2cocGxheWVyLnRyYW5zcG9ydF9jb3N0KSwKICBkZgopCgpzdW1tYXJ5KHJlZykKYGBgCgpBIHJlZ3Jlc3Npb24gd2l0aCBub3JtYWxpemVkIHByb2ZpdCBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LCBhbmQgaGFzIHNpbWlsYXIgcmVzdWx0cyBhcyB0aGUgcHJpY2UtdHJhbnNmb3JtZWQgbG9nLWxvZy4KCk5vdyB3ZSB3b3VsZCBpbnRlcnByZXQgJFxiZXRhXzMkIGFzICIqdGhlIDItcGxheWVyIGdhbWUsIGEgb25lIHVuaXQgaW5jcmVhc2UgaW4gdHJhbnNwb3J0IGNvc3QgZGVjcmVhc2VzIHByb2ZpdCBieSAwLjIzIHN0YW5kYXJkIGRldmlhdGlvbnMgY29tcGFyZWQgdG8gdGhlIDQtcGxheWVyIGdhbWUqIiAoaWYgbXkgaW50ZXJwcmV0YXRpb24gaXMgY29ycmVjdCwgdGhhdCBjb3VsZCBwcm9iYWJseSBiZSBzYWlkIGJldHRlcikuICAKCgojIyMjIExldmVsIC0gTG9nCgpgYGB7ciwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGVjaG8gPSBGQUxTRSwgZXJyb3I9RkFMU0UsIGNhY2hlPUZBTFNFfQoKCnJlZyA9IGxtKAogIHByb2ZpdH4gbG9nKHBsYXllci50cmFuc3BvcnRfY29zdCkgKyB0d29QbGF5ZXIgKyB0d29QbGF5ZXI6bG9nKHBsYXllci50cmFuc3BvcnRfY29zdCksCiAgZGYKKQoKc3VtbWFyeShyZWcpCmBgYAoKCkEgUmVndWxhciBsZXZlbC1sb2cgcmVncmVzc2lvbiBoYXMgYHBsYXllci50cmFuc3BvcnRfY29zdDp0d29QbGF5ZXJgIGlzIGluc2lnbmlmaWNhbnQuIAoKCi0tLS0tCgotLSoqRGF2ZSoqOiBIb3cgZGlkIHlvdSBtZWFzdXJlIGNvbGx1c2lvbiBpbiB5b3VyIG90aGVyIEhvdGVsbGluZ3Mgd29yaz8gSSdkIGxpa2UgdG8ga25vdyBpZiAiY29sbHVzaW9uIiBpcyBoaWdoZXIgaW4gMnAgc2Vzc2lvbnMgYW5kLCBpZiBpdCdzIGhpZ2hlciBpbiBsb3cgdHJhbnNwb3J0IGNvc3QgcGVyaW9kcywgaW4gYm90aCAycCBhbmQgNHAuIExvb2tpbmcgYXQgdGhlIHNlY29uZCBmaWd1cmUgZm9yIDJwLCBpdCBsb29rcyBsaWtlIHRoZSBwcm9maXRzIHRoYXQgYXJlIG11Y2ggaGlnaGVyIHRoYW4gdGhlIGJ1bGsgb2YgdGhlIG1hc3MgKHdoaWNoIGlzIHN1Z2dlc3RpdmUgb2YgY29sbHVzaW9uKSwgYW5kIHRoaXMgaGFwcGVucyBtb3JlIGZyZXF1ZW50bHkgYXQgbG93IHRyYW5zcG9ydCBjb3N0cy4gWW91IHNlZSB0aGUgc2FtZSBzb3J0IG9mIHBhdHRlcm4gaW4gdGhlIHNlY29uZCBmaWd1cmUgaW4gNHAsIGJ1dCBtb3JlIGxlc3MgcHJldmFsZW50LiBWaXN1YWxseSwgaXQgc2VlbXMgc3VnZ2VzdGl2ZSBvZiB0aGVzZSBhZGRpdGlvbmFsIGh5cG90aGVzZXMuLS0KCldlIGhhZCBhIGZldyBtZWFzdXJlcyBvZiBjb2xsdXNpb24uIFNpbmNlIHdlIGhhZCBhIGNvbnRpbnVvdXMgdGltZSBkYXRhLCB3ZSBsb29rZWQgYXQgaG93IHN1YmplY3RzIHJlc3BvbmRlZCB0byBvdGhlcnMnIGFjdGlvbiBzZWxlY3Rpb24uIEUuZy4sIChpbiB0aGUgcHJpY2UgYW5kIGxvY2F0aW9uIEhvdGVsbGluZyBzZXR0aW5nKSwgd2hlbiBhIHBsYXllciBkaWQgY2hhbmdlIHRoZWlyIGFjdGlvbiwgZGlkIHRoZXkgbW92ZSBsb2NhdGlvbiBhbmQgcHJpY2UgaW4gYSB3YXkgdGhhdCBvcGVuZWQgdXAgdGhlIHBvc3NpYmlsaXR5IG9mIGdldHRpbmcgaGlnaGVyIGpvaW50IHByb2ZpdCAod2hpY2ggdXN1YWxseSBtZWFudCByZWR1Y2luZyBvbmUncyBwcm9maXQpPyBPciBkaWQgdGhleSBhY3QgImNvbXBldGl0aXZlbHkiLCBpbmNyZWFzaW5nIG93biBwcm9maXQgYXQgZXhwZW5zZSBvZiBjb3VudGVycGFydHk/IEFzIGFub3RoZXIgbWVhc3VyZSBvZiBjb2xsdXNpb24sIGlmIHRoZXJlIHdlcmUgam9pbnQgcG9zaXRpdmUgcHJvZml0cywgZGlkIHBsYXllcnMgcmVtYWluIHN0YXRpb25hcnk/IAoKQ29sbHVzaW9uIE1ldHJpY3M6CgotIEluIHRoaXMgc2V0dGluZywgd2UgbWlnaHQgY29uc2lkZXIgdGhlIGRpcmVjdCBhbmQgbWFnbml0dWRlIG9mIHByaWNlIGNoYW5nZXMuIFdoZXJlIGNoYW5nZXMgaW4gcHJpY2VzIGdlbmVyYWxseSBkb3duPyBvciB1cD8gVGhpcyBoYXMgcHJvYmxlbXMgc2luY2UgcGxheWVycyBjb2xsaWRpbmcgYXQgdmVyeSBoaWdoIHByaWNlcyBkb24ndCBoYXZlIHJvb20gdG8gc2lnbmFsIGZ1cnRoZXIgY29sbHVzaW9uIGJ5IGluY3JlYXNpbmcgcHJpY2VzLiAKLSAuLi4gSSBkb24ndCBoYXZlIGEgZ29vZCByZXNwb25zZSB0byB0aGlzLi4uCgpSZWdhcmRpbmcgeW91ciBvYnNlcnZhdGlvbiB0aGF0IGxvb2tpbmcgYXQgcHJvZml0IGFuZCB0cmFuc3BvcnQgY29zdHMsIHRoZSB2ZXJ5IGxvdyB0cmFuc3BvcnQgY29zdCB0cmVhdG1lbnRzIGhhZCBsb3dlciB0aGFuIGF2ZXJhZ2UgcHJvZml0LCBidXQgaGFkIGEgZmV3IG9ic2VydmF0aW9ucyB3aXRoIHZlcnkgaGlnaCBwcm9maXQuIElzbid0IHRoaXMgbW9yZSBhICJ0ZWNobmljYWwgYXJ0aWZhY3QiIChwcm9iYWJseSBub3QgdGhlIHJpZ2h0IHRlcm0uLi4pLCB3aGVyZSB3aXRoIGB0ID0gMC4xYCBpZiB5b3VyIG9wcG9uZW50IGhhcyBoaWdoIHByaWNlcywgYSBzbGlnaHRseSBsb3dlciBwcmljZSB3aWxsIHNlcmlvdXNseSB1bmRlcmN1dCB0aGVtIGFuZCBjYXB0dXJlIGEgbGFyZ2UgcG9ydGlvbiBvZiB0aGUgbWFya2V0LiBXaGVyZWFzIHdpdGggaGlnaCB0cmFuc3BvcnQgY29zdCwgeW91IG5lZWQgdG8gYmUgc2VyaW91c2x5IGJlbG93IHlvdXIgb3Bwb25lbnQgdG8gdW5kZXJjdXQgdGhlaXIgcHJpY2UgYW5kIGNhcHR1cmUgc2VyaW91cyBtYXJrZXQgc2hhcmUuIFNvLCBpdCB3b3VsZCBzZWVtIHRvIG1lIHRoYXQgdGhlcmUgYXJlIGEgZmV3IGNhc2VzIHdpdGggbG93IHRyYW5zcG9ydCBjb3N0cyB3aGVyZSBhICJnb29kIiBwbGF5ZXIgd2FzIHVwIGFnYWluc3QgYSBjYXJlbGVzcyBvbmUsIGFuZCBpbiB0aGF0IHBlcmlvZCB0aGUgZ29vZCBwbGF5ZXIgZWFybmVkIHRoZSByYXJlLCB2ZXJ5IGhpZ2ggcHJvZml0IHRoYXQgcGVyaW9kLiAKCgoKIyBUd28tUGxheWVyIEdhbWUKClNlc3Npb25zIHJ1biBzbyBmYXIsIAoKYGBge3IsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBlY2hvID0gRkFMU0UsIGVycm9yPUZBTFNFfQoKCiMgbmFtZXMoc2VzRGF0MnApCiMgdW5pcXVlKHNlc0RhdDJwJHNlc3Npb24uY29kZSkKIyBkZiA9IHNlc0RhdDJwICU+JQojICAgZ3JvdXBfYnkoc2Vzc2lvbi5jb2RlLHBsYXllci5wZXJpb2RfbnVtYmVyLHBsYXllci50cmFuc3BvcnRfY29zdCkgJT4lCiMgICBzdW1tYXJpc2UoCiMgICAgIG1lYW5fcHJvZml0ID0gbWVhbihwbGF5ZXIucm91bmRfcGF5b2ZmICogMTAwKSwKIyAgICAgcGxheWVyX2NvdW50ID0gbGVuZ3RoKHVuaXF1ZShwYXJ0aWNpcGFudC5jb2RlKSksCiMgICAgIGF2Z19wZXJpb2RzX3BlclBsYXllciA9IGxlbmd0aCgocGxheWVyLnBlcmlvZF9udW1iZXIpKSwKIyAgICAgcm91bmRfY291bnQgPSBsZW5ndGgodW5pcXVlKHN1YnNlc3Npb24ucm91bmRfbnVtYmVyKSkKIyAgICkKIyBrYWJsZSgKIyAgIGZvcm1hdCA9ICJtYXJrZG93biIsCiMgICBkZiwgIGFsaWduID0gYygiYyIpCiMgICAjIGNvbC5uYW1lcyA9IGMoIiIsIiIsIiIsIkF2ZyBUYXNrIDEgUkVUIFNjb3JlIiwiQXZnIFRhc2sgMiBSRVQgU2NvcmUiLCJBdmcgVGFzayAzIFJFVCBTY29yZSIsIlRvdXJuIiwgIlNzIikKIyApCgpkZiA9IHNlc0RhdDJwICU+JQogIGdyb3VwX2J5KHNlc3Npb24uY29kZSkgJT4lCiAgc3VtbWFyaXNlKAogICAgbl9zdWJqZWN0cyA9IGxlbmd0aCh1bmlxdWUocGFydGljaXBhbnQuY29kZSkpLAogICAgZGF0ZSA9IG1pbihwYXJ0aWNpcGFudC50aW1lX3N0YXJ0ZWQpCiAgKQprYWJsZSgKICBmb3JtYXQgPSAibWFya2Rvd24iLAogIGRmLCAgYWxpZ24gPSBjKCJjIikKICAjIGNvbC5uYW1lcyA9IGMoIiIsIiIsIiIsIkF2ZyBUYXNrIDEgUkVUIFNjb3JlIiwiQXZnIFRhc2sgMiBSRVQgU2NvcmUiLCJBdmcgVGFzayAzIFJFVCBTY29yZSIsIlRvdXJuIiwgIlNzIikKKQoKCgpgYGAKCgpgYGB7ciwgZWNobz1GQUxTRSwgdGlkeT1UfQojNCBlcnJvciBjaGVjawoKIyBuYW1lcyhzZXNEYXQ0cCkKIyB1bmlxdWUoc2VzRGF0NHAkc2Vzc2lvbi5jb2RlKQojIGRmID0gc2VzRGF0NHAgJT4lCiMgICBncm91cF9ieShzZXNzaW9uLmNvZGUscGxheWVyLnBlcmlvZF9udW1iZXIscGxheWVyLnRyYW5zcG9ydF9jb3N0KSAlPiUKIyAgIHN1bW1hcmlzZSgKIyAgICAgbWVhbl9wcm9maXQgPSBtZWFuKHBsYXllci5yb3VuZF9wYXlvZmYgKiAxMDApLAojICAgICBwbGF5ZXJfY291bnQgPSBsZW5ndGgodW5pcXVlKHBhcnRpY2lwYW50LmNvZGUpKSwKIyAgICAgcm91bmRfY291bnQgPSBsZW5ndGgodW5pcXVlKHN1YnNlc3Npb24ucm91bmRfbnVtYmVyKSkKIyAgICkKIyAKIyBrYWJsZSgKIyAgIGZvcm1hdCA9ICJtYXJrZG93biIsIAojICAgZGYsICBhbGlnbiA9IGMoImMiKQojICAgIyBjb2wubmFtZXMgPSBjKCIiLCIiLCIiLCJBdmcgVGFzayAxIFJFVCBTY29yZSIsIkF2ZyBUYXNrIDIgUkVUIFNjb3JlIiwiQXZnIFRhc2sgMyBSRVQgU2NvcmUiLCJUb3VybiIsICJTcyIpCiMgKQpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFLCB0aWR5PVR9CiM0IGVycm9yIGNoZWNrCgojIG5hbWVzKHNlc0RhdDRwKQojIHVuaXF1ZShzZXNEYXQ0cCRzZXNzaW9uLmNvZGUpCiMgZGYgPSBzZXNEYXQ0cCAlPiUKIyAgIGdyb3VwX2J5KHNlc3Npb24uY29kZSxwYXJ0aWNpcGFudC5jb2RlLHBsYXllci5wZXJpb2RfbnVtYmVyLHBsYXllci50cmFuc3BvcnRfY29zdCkgJT4lCiMgICBzdW1tYXJpc2UoCiMgICAgIG1lYW5fcHJvZml0ID0gbWVhbihwbGF5ZXIucm91bmRfcGF5b2ZmKSwKIyAgICAgbWVhbl9wcm9maXQyID0gbWVhbihwbGF5ZXIucm91bmRfcGF5b2ZmKSAqIGxlbmd0aChwbGF5ZXIucm91bmRfcGF5b2ZmKSwKIyAgICAgc3VtX3Byb2ZpdCA9IHN1bShwbGF5ZXIucm91bmRfcGF5b2ZmKSwKIyAgICAgcGxheWVyLmN1bXVsYXRpdmVfcm91bmRfcGF5b2ZmID0gbWF4KHBsYXllci5jdW11bGF0aXZlX3JvdW5kX3BheW9mZiksCiMgICAgIHBsYXllcl9jb3VudCA9IGxlbmd0aCh1bmlxdWUocGFydGljaXBhbnQuY29kZSkpLAojICAgICByb3VuZF9jb3VudCA9IGxlbmd0aCh1bmlxdWUoc3Vic2Vzc2lvbi5yb3VuZF9udW1iZXIpKQojICAgKQoKYGBgCgoKCiMjIFByb2ZpdCBhbmQgVHJhbnNwb3J0IENvc3RzCgpBIGZhaXJseSBjbGVhciBzdG9yeSBoZXJlLiBUaGUgZmlndXJlIGJlbG93IHBsb3RzIGF2ZXJhZ2UgcGF5b2ZmcyBmb3IgZWFjaCBzZXNzaW9uLiBUaGlzIGF2ZXJhZ2VzIHBheW9mZnMgb3ZlciBhbGwgc3ViamVjdCBpbiBhbGwgcGVyaW9kcyB3aXRoaW4gb25lIHNlc3Npb24uIAoKYGBge3IsIGVjaG89RkFMU0V9CmdncGxvdCgKICBzZXNEYXQycCAlPiUKICAgIGdyb3VwX2J5KHNlc3Npb24uY29kZSxwbGF5ZXIudHJhbnNwb3J0X2Nvc3QscGxheWVyLnRyYW5zcG9ydF9jb3N0KSAlPiUKICAgIHN1bW1hcmlzZSgKICAgICAgbWVhbl9wcm9maXQgPSBtZWFuKHBsYXllci5yb3VuZF9wYXlvZmYgKiBtYXgoc3Vic2Vzc2lvbi5yb3VuZF9udW1iZXIpKQogICAgKSAlPiUKICAgIGZpbHRlcigKICAgICAgIWlzLm5hKG1lYW5fcHJvZml0KQogICAgKQopICsKICBnZW9tX3BvaW50KAogICAgYWVzKAogICAgICB4ID0gYXMuZmFjdG9yKHBsYXllci50cmFuc3BvcnRfY29zdCksCiAgICAgIHkgPSBtZWFuX3Byb2ZpdCwKICAgICAgY29sb3IgPSBwYXN0ZShzZXNzaW9uLmNvZGUscGxheWVyLnRyYW5zcG9ydF9jb3N0KQogICAgKQogICkKYGBgCgpOb3RlIHRoYXQgdGhlIHRyYW5zcG9ydCBjb3N0IG9mIDAuMjUgaGFkIGFuIGVycm9yIGluIGl0cyBpbXBsZW1lbnRhdGlvbi4gSW4gMC4yNSB0cmFuc3BvcnQgY29zdCBwZXJpb2RzLCBzdWJqZWN0cyBvbmx5IGhhZCA1IHN1YnBlcmlvZHMsIG5vdCB0aGUgMjAgYWxsIG90aGVyIHBlcmlvZHMgaGFkLiBUaGlzIG1vc3QgbGlrZWx5IGV4cGxhaW5zIHRoZSBvZGQgcmVzdWx0LiAKCgpJbiB0aGUgdGFibGUgYmVsb3cgSSBjb21wYXJlIGF2ZXJhZ2UgcGF5b2ZmIGJldHdlZW4gdHJhbnNwb3J0IGNvc3QgdHJlYXRtZW50cywgYXQgdGhlIHNlc3Npb24gbGV2ZWwuCgpUaGUgc3RhbmRhcmQgZXJyb3JzIGFyZSBwcm9iYWJseSBub3QgdGhlIHdheSB5b3Ugd2FudCB0byBkbyBpdC4gSSdtIHVzaW5nIGV2ZXJ5IG9ic2VydmF0aW9uIGZyb20gZWFjaCBzdWJwZXJpb2Qgb2YgZWFjaCBwZXJpb2QuIFdlIHByb2JhYmx5IHdhbnQgdG8gY29tcGFyZSBhdmVyYWdlIHBheW9mZnMgcGVyIHBlcmlvZCBvciBwZXIgc2Vzc2lvbi4gQnV0IHN0aWxsLi4uCgpgYGB7ciwgZWNobyA9IEYsIGV2YWwgPSBULCB0aWR5ID0gVH0KZGYgPSBzZXNEYXQycCAlPiUKICB1bmdyb3VwKCkgJT4lCiAgZ3JvdXBfYnkocGxheWVyLnRyYW5zcG9ydF9jb3N0KSAlPiUKICBtdXRhdGUoCiAgICBwbGF5ZXIucm91bmRfcGF5b2ZmID0gcGxheWVyLnJvdW5kX3BheW9mZiAqIG1heChzdWJzZXNzaW9uLnJvdW5kX251bWJlcikgI2RlYWwgd2l0aCBmJ2luZyB0PTAuMjUuLi4KICApICU+JQogIHN1bW1hcmlzZSgKICAgIG49bigpLAogICAgbWVhbl9wcm9maXQgPSBtZWFuKHBsYXllci5yb3VuZF9wYXlvZmYpLCAgCiAgICBtZWRpYW5fcHJvZml0ID0gbWVkaWFuKHBsYXllci5yb3VuZF9wYXlvZmYpLAogICAgc2VfcHJvZml0ID0gc2QocGxheWVyLnJvdW5kX3BheW9mZikvKG4pXjAuNQogICkgCgprYWJsZSgKICBmb3JtYXQgPSAibWFya2Rvd24iLCAKICBkZiwgIGFsaWduID0gYygiYyIpCiAgIyBjb2wubmFtZXMgPSBjKCIiLCIiLCIiLCJBdmcgVGFzayAxIFJFVCBTY29yZSIsIkF2ZyBUYXNrIDIgUkVUIFNjb3JlIiwiQXZnIFRhc2sgMyBSRVQgU2NvcmUiLCJUb3VybiIsICJTcyIpCikKYGBgCgpOb3csIGJlbG93LCB3ZSBjYWxjdWxhdGUgc3RhbmRhcmQgZXJyb3Igd2l0aCBtZWFuIHBheW9mZnMgYXQgdGhlIHNlc3Npb24rcGVyaW9kK3RyYW5zcG9ydCBjb3N0IGxldmVsLiAKClRoZXJlIGFyZSBmYXIgZmV3ZXIgb2JzZXJ2YXRpb25zLCBtYWtpbmcgb3VyIHN0YW5kYXJkIGVycm9yIG11Y2ggbGFyZ2VyLiBIb3dldmVyLCBzdGlsbCwgdGhlIHZlcnkgbG93IHRyYW5zcG9ydCBjb3N0IGFyZSBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tIHRoZSB0d28gdHJhbnNwb3J0IGNvc3RzIGluIHRoZSBoaWdoIHJhbmdlLiAKCmBgYHtyLCBlY2hvID0gRiwgZXZhbCA9IFQsIHRpZHkgPSBUfQpkZiA9IHNlc0RhdDJwICU+JQogIHVuZ3JvdXAoKSAlPiUKICBncm91cF9ieShzZXNzaW9uLmNvZGUsIHBsYXllci50cmFuc3BvcnRfY29zdCwgcGxheWVyLnBlcmlvZF9udW1iZXIpICU+JSAKICBtdXRhdGUoCiAgICBwbGF5ZXIucm91bmRfcGF5b2ZmID0gcGxheWVyLnJvdW5kX3BheW9mZiAqIG1heChzdWJzZXNzaW9uLnJvdW5kX251bWJlcikgI2RlYWwgd2l0aCBmJ2luZyB0PTAuMjUuLi4KICApICU+JQogIHN1bW1hcmlzZSgKICAgIG49bigpLAogICAgbWVhbl9wcm9maXQgPSBtZWFuKHBsYXllci5yb3VuZF9wYXlvZmYpLCAgCiAgICBtZWRpYW5fcHJvZml0ID0gbWVkaWFuKHBsYXllci5yb3VuZF9wYXlvZmYpLAogICAgc2VfcHJvZml0ID0gc2QocGxheWVyLnJvdW5kX3BheW9mZikvKG4pXjAuNQogICkgJT4lCiAgZ3JvdXBfYnkocGxheWVyLnRyYW5zcG9ydF9jb3N0KSAlPiUKICBzdW1tYXJpc2UoCiAgICBuPW4oKSwKICAgIG1lYW5fcHJvZml0XyA9IG1lYW4obWVhbl9wcm9maXQpLCAKICAgIHNlX3Byb2ZpdCA9IHNkKG1lYW5fcHJvZml0KS8obileMC41CiAgKQoKa2FibGUoCiAgZm9ybWF0ID0gIm1hcmtkb3duIiwgCiAgZGYsICBhbGlnbiA9IGMoImMiKQogICMgY29sLm5hbWVzID0gYygiIiwiIiwiIiwiQXZnIFRhc2sgMSBSRVQgU2NvcmUiLCJBdmcgVGFzayAyIFJFVCBTY29yZSIsIkF2ZyBUYXNrIDMgUkVUIFNjb3JlIiwiVG91cm4iLCAiU3MiKQopCmBgYAoKCgpgYGB7ciwgZWNobz1GQUxTRX0KZ2dwbG90KAogc2VzRGF0MnAgJT4lCiAgdW5ncm91cCgpICU+JQogIGdyb3VwX2J5KHNlc3Npb24uY29kZSwgcGFydGljaXBhbnQuY29kZSwgcGxheWVyLnRyYW5zcG9ydF9jb3N0LHBsYXllci5wZXJpb2RfbnVtYmVyKSAlPiUKICBtdXRhdGUoCiAgICBwbGF5ZXIucm91bmRfcGF5b2ZmID0gcGxheWVyLnJvdW5kX3BheW9mZiAqIG1heChzdWJzZXNzaW9uLnJvdW5kX251bWJlcikgI2RlYWwgd2l0aCBmJ2luZyB0PTAuMjUuLi4KICApICU+JQogICBzdW1tYXJpc2UoCiAgICAgbWVhbl9wcm9maXQgPSBtZWFuKHBsYXllci5yb3VuZF9wYXlvZmYpCiAgICkKKSArCiAgICBnZW9tX3Zpb2xpbigKICAgIGFlcygKICAgICAgeCA9IGFzLmZhY3RvcihwbGF5ZXIudHJhbnNwb3J0X2Nvc3QpLAogICAgICB5ID0gbWVhbl9wcm9maXQKICAgICksIGFscGhhID0gLjgKICApICsKICBnZW9tX2ppdHRlcigKICAgIGFlcygKICAgICAgeCA9IGFzLmZhY3RvcihwbGF5ZXIudHJhbnNwb3J0X2Nvc3QpLAogICAgICB5ID0gbWVhbl9wcm9maXQsCiAgICAgIGNvbG9yID0gcGxheWVyLnBlcmlvZF9udW1iZXIKICAgICksIAogICAgYWxwaGEgPSAuNywKICAgIHdpZHRoID0gLjEsIGhlaWdodCA9IDAKICApICsKICB0aGVtZV9idygpCmBgYAoKTG9va2luZyBhdCBkaXN0cmlidXRpb25zIGluIGFub3RoZXIgd2F5LCAKCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTMuNSwgZmlnLndpZHRoPTh9CmdncGxvdCgKIHNlc0RhdDJwICU+JQogIHVuZ3JvdXAoKSAlPiUKICAgIGZpbHRlcigKICAgICAgIWlzLm5hKHBsYXllci5yb3VuZF9wYXlvZmYpLAogICAgICBwbGF5ZXIudHJhbnNwb3J0X2Nvc3QgIT0gMC4yNQogICAgKSAlPiUKICBncm91cF9ieShzZXNzaW9uLmNvZGUsIHBhcnRpY2lwYW50LmNvZGUsIHBsYXllci50cmFuc3BvcnRfY29zdCxwbGF5ZXIucGVyaW9kX251bWJlcikgJT4lCiAgbXV0YXRlKAogICAgcGxheWVyLnJvdW5kX3BheW9mZiA9IHBsYXllci5yb3VuZF9wYXlvZmYgKiBtYXgoc3Vic2Vzc2lvbi5yb3VuZF9udW1iZXIpICNkZWFsIHdpdGggZidpbmcgdD0wLjI1Li4uCiAgKSAlPiUKICAgc3VtbWFyaXNlKAogICAgIG1lYW5fcHJvZml0ID0gbWVhbihwbGF5ZXIucm91bmRfcGF5b2ZmKQogICApCiAgKSArCiAgICBnZW9tX2RlbnNpdHkoCiAgICBhZXMoCiAgICAgIHggID0gbWVhbl9wcm9maXQsCiAgICAgIGNvbG91ciA9IGFzLmZhY3RvcihwbGF5ZXIudHJhbnNwb3J0X2Nvc3QpLAogICAgICBmaWxsID0gYXMuZmFjdG9yKHBsYXllci50cmFuc3BvcnRfY29zdCksCiAgICAgIGdyb3VwID0gYXMuZmFjdG9yKHBsYXllci50cmFuc3BvcnRfY29zdCkKICAgICksIGFscGhhID0gLjEKICApICsKICB0aGVtZV9idygpCmBgYAoKQmVsb3csIHdlIGhhdmUgdGhlIGRpc3RyaWJ1dGlvbiBvZiBhbGwgc3VicGVyaW9kL3JvdW5kIHByb2ZpdHMuIFdpdGhpbiBlYWNoIHRyYW5zcG9ydCBjb3N0cyBncm91cCwgY29sb3JzIHJlcHJlc2VudCBhIHNpbmdsZSBwZXJpb2QuIFdlIHNlZSByZW1hcmthYmx5IGNvbnNpc3RlbnQgZGlzdHJpYnV0aW9ucyBvZiBwcm9maXQgd2l0aGluIHRyYW5zcG9ydC1jb3N0IGdyb3VwcywgYW5kIG5vdGljZWFibHkgZGlmZmVyZW50IGRpc3RyaWJ1dGlvbnMgYmV0d2VlbiB0cmFuc3BvcnQgY29zdCBncm91cHMuCgoKCgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLmhlaWdodD0zLjUsIGZpZy53aWR0aD04fQpnZ3Bsb3QoCiBzZXNEYXQycCAlPiUKICB1bmdyb3VwKCkgJT4lCiAgZ3JvdXBfYnkoc2Vzc2lvbi5jb2RlLCBwYXJ0aWNpcGFudC5jb2RlLCBwbGF5ZXIudHJhbnNwb3J0X2Nvc3QscGxheWVyLnBlcmlvZF9udW1iZXIpICU+JQogIG11dGF0ZSgKICAgIHBheW9mZiA9IHBsYXllci5yb3VuZF9wYXlvZmYgKiBtYXgoc3Vic2Vzc2lvbi5yb3VuZF9udW1iZXIpICNkZWFsIHdpdGggZidpbmcgdD0wLjI1Li4uCiAgKQopICsKICAgIGdlb21fZGVuc2l0eSgKICAgIGFlcygKICAgICAgeCAgPSBwYXlvZmYsCiAgICAgIGNvbG91ciA9IGFzLmZhY3RvcihwbGF5ZXIucGVyaW9kX251bWJlciksCiAgICAgIGZpbGwgPSBhcy5mYWN0b3IocGxheWVyLnBlcmlvZF9udW1iZXIpCiAgICApLCBhbHBoYSA9IC4yCiAgKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSArIAogIGZhY2V0X2dyaWQoLiB+cGxheWVyLnRyYW5zcG9ydF9jb3N0KSAKCmBgYAoKCk5vdywgd2Ugc2VlIHRoZSBkaXN0cmlidXRpb24gb2YgcHJvZml0cyBvdmVyIGVhY2ggdHJhbnNwb3J0IGNvc3RzLCBhdmVyYWdlZCBvdmVyIGEgZ2l2ZW4gc2Vzc2lvbitwZXJpb2QgKGxlc3MgZ3JhbnVsYXIgdGhhbiBhYm92ZSkuICAKCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTMuNSwgZmlnLndpZHRoPTh9CmdncGxvdCgKICBzZXNEYXQycCAlPiUKICAgIGdyb3VwX2J5KHNlc3Npb24uY29kZSxwbGF5ZXIudHJhbnNwb3J0X2Nvc3QpICU+JQogICAgZ3JvdXBfYnkoc2Vzc2lvbi5jb2RlLCBwYXJ0aWNpcGFudC5jb2RlLCBwbGF5ZXIudHJhbnNwb3J0X2Nvc3QscGxheWVyLnBlcmlvZF9udW1iZXIpICU+JSAKICAgIHN1bW1hcmlzZSgKICAgICAgbWVhbl9wcm9maXQgPSBtZWFuKHBsYXllci5yb3VuZF9wYXlvZmYgKiBtYXgoc3Vic2Vzc2lvbi5yb3VuZF9udW1iZXIpKSAKICAgICkgJT4lCiAgICBmaWx0ZXIoCiAgICAgICFpcy5uYShtZWFuX3Byb2ZpdCkKICAgICkKKSArCiAgICBnZW9tX2RlbnNpdHkoCiAgICBhZXMoCiAgICAgIHggID0gbWVhbl9wcm9maXQsCiAgICAgIGNvbG91ciA9IGFzLmZhY3RvcihwbGF5ZXIucGVyaW9kX251bWJlciksCiAgICAgIGZpbGwgPSBhcy5mYWN0b3IocGxheWVyLnBlcmlvZF9udW1iZXIpCiAgICApLCBhbHBoYSA9IC4xCiAgKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSArIAogIGZhY2V0X2dyaWQoLiB+cGxheWVyLnRyYW5zcG9ydF9jb3N0KQpgYGAKCgoKVG8gc3VtbWFyaXplIGEgbGl0dGxlOiAKCi0gVGhlIGxvd2VyIHRoZSB0cmFuc3BvcnQgY29zdCB0aGUgbG93ZXIgdGhlIHByb2ZpdCB0byB0aGUgc3ViamVjdC4gCgotIFRoZXJlIGlzIGEgY2xlYXIgYW5kIGxpa2VseSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IGRpZmZlcmVuY2UgYmV0d2VlbiBhdmVyYWdlIHBheW9mZnMgKG91ciBwcm94eSBmb3IgY29vcGVyYXRpb24gcmF0ZXMpIGJldHdlZW4gbG93IHRyYW5zcG9ydCBjb3N0IGB0ID0gMC4xYCBhbmQgaGlnaCBgdCA9IDEuMGAuCgotIFRoZSBkaWZmZXJlbmNlIGJldHdlZW4gYHQgPSAxLjBgIGFuZCBgdCA9IDAuNzVgIGRvZXMgbm90IHlldCBhcHBlYXIgdG8gYmUgc2lnbmlmaWNhbnQuIAoKCiMjIyBQZXJpb2QgRWZmZWN0CgpUaGVyZSBkb2VzIG5vdCBhcHBlYXIgdG8gYmUgYW55IHBlcmlvZCBlZmZlY3QuIEkgc3VzcGVjdGVkIHRoYXQgcGVyaGFwcyBpbiBsYXRlciBwZXJpb2RzIHdlJ2Qgc2VlIGNvbnNpc3RlbnRseSBsb3dlciBvciBoaWdoZXIgbGV2ZWxzIG9mIGNvb3BlcmF0aW9ucy9wYXlvZmZzLiBUaGF0IGRvZXMgbm90IGFwcGVhciB0byBiZSB0aGUgY2FzZQoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9My41LCBmaWcud2lkdGg9OH0KZ2dwbG90KAogIHNlc0RhdDJwICU+JQogICAgZ3JvdXBfYnkoc2Vzc2lvbi5jb2RlLCBwYXJ0aWNpcGFudC5jb2RlLCBwbGF5ZXIudHJhbnNwb3J0X2Nvc3QscGxheWVyLnBlcmlvZF9udW1iZXIpICU+JSAKICAgIHN1bW1hcmlzZSgKICAgICAgbWVhbl9wcm9maXQgPSBtZWFuKHBsYXllci5yb3VuZF9wYXlvZmYgKiAyMCkKICAgICkgJT4lCiAgICBmaWx0ZXIoCiAgICAgICFpcy5uYShtZWFuX3Byb2ZpdCksCiAgICAgIHBsYXllci50cmFuc3BvcnRfY29zdCAhPSAwLjI1CiAgICApCikgKwogICAgZ2VvbV9ib3hwbG90KAogICAgYWVzKAogICAgICB4ID0gYXMuZmFjdG9yKHBsYXllci5wZXJpb2RfbnVtYmVyKSwKICAgICAgeSA9IG1lYW5fcHJvZml0CiAgICApLCBhbHBoYSA9IC4zCiAgKSArCiAgZ2VvbV9qaXR0ZXIoCiAgICBhZXMoCiAgICAgIHggPSBhcy5mYWN0b3IocGxheWVyLnBlcmlvZF9udW1iZXIpLAogICAgICB5ID0gbWVhbl9wcm9maXQKICAgICksIGFscGhhID0gLjcKICApCmBgYAoKCgojIyBQcmljZXMgYW5kIFRyYW5zcG9ydCBDb3N0cwoKSG93IGRvIHByaWNlcyByZWxhdGVkIHRvIHRyYW5zcG9ydCBjb3N0PyAKSG93IGRvZXMgcHJpY2Ugc3RpY2tpbmVzcyByZWxhdGVkIHRvIHRyYW5zcG9ydCBjb3N0PwoKClRoZSBmaWd1cmUgYmVsb3cgcGxvdHMgcHJpY2VzIGZvciBlYWNoIHNlc3Npb24uIFRoaXMgYXZlcmFnZXMgcGF5b2ZmcyBvdmVyIGFsbCBzdWJqZWN0IGluIGFsbCBwZXJpb2RzIHdpdGhpbiBvbmUgdHJhbnNwb3J0IGNvc3QgdHJlYXRtZW50IGdyb3VwLiAKCi0gVGhlIHZpb2xlbiBzaG93cyB0aGUgZGlzdHJpYnV0aW9uIG9mIHByaWNlcyB3aXRoaW4gdGhhdCB0cmFuc3BvcnQgY29zdCB0cmVhdG1lbnQgZ3JvdXAuIAotIFRoZSBncmV5IHJpYmJlbiBzaG93cyB0aGUgZmlyc3QgYW5kIHRoaXJkIHF1YXJ0aWxlIG9mIHByaWNlcywgdGhhdCBpcywgNTBcJSBvZiBhbGwgcHJpY2VzIHNlbGVjdGVkIGJ5IHN1YmplY3RzIGluIHRoZSB0cmVhdG1lbnQgZ3JvdXAgd2VyZSB3aXRoaW4gdGhlIHJpYmJpbi4gCi0gVGhlIGxpbmUgc2hvd3MgdGhlIG1lZGlhbiBmb3IgZWFjaCB0cmFuc3BvcnQgY29zdCB0cmVhdG1lbnQgZ3JvdXAuIAoKV2Ugc2VlIGEgZ2VuZXJhbGx5IHBvc2l0aXZlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHByaWNlcyBhbmQgdHJhbnNwb3J0IGNvc3RzLiAKCmBgYHtyLCBlY2hvPUZBTFNFfQoKZ2dwbG90KAogIHNlc0RhdDJwICU+JQogICAgZ3JvdXBfYnkocGxheWVyLnRyYW5zcG9ydF9jb3N0KSAlPiUKICAgIHN1bW1hcmlzZSgKICAgICAgcHJpY2VfcTc1ID0gcXVhbnRpbGUocGxheWVyLnByaWNlLCAwLjc1KSwKICAgICAgcHJpY2VfcTUwID0gcXVhbnRpbGUocGxheWVyLnByaWNlLCAwLjUpLAogICAgICBwcmljZV9xMjUgPSBxdWFudGlsZShwbGF5ZXIucHJpY2UsIDAuMjUpLAogICAgICBtZWFuX3ByaWNlID0gbWVhbihwbGF5ZXIucHJpY2UpCiAgICApIAopICsKICAgIGdlb21fdmlvbGluKAogICAgZGF0YSA9IHNlc0RhdDJwLAogICAgYWVzKAogICAgICB4ID0gcGxheWVyLnRyYW5zcG9ydF9jb3N0LAogICAgICB5ID0gcGxheWVyLnByaWNlLAogICAgICBncm91cCA9IHBsYXllci50cmFuc3BvcnRfY29zdAogICAgKSwKICAgIGFscGhhID0gMC4zLAogICAgY29sb3IgPSAiZ3JleTcwIgogICkgKwogIGdlb21fcmliYm9uKAogICAgYWVzKAogICAgICB4ID0gKHBsYXllci50cmFuc3BvcnRfY29zdCksCiAgICAgIHltYXggPSBwcmljZV9xNzUsCiAgICAgIHltaW4gPSBwcmljZV9xMjUKICAgICksCiAgICBhbHBoYSA9IC4yCiAgKSArCiAgZ2VvbV9saW5lKAogICAgYWVzKAogICAgICB4ID0gcGxheWVyLnRyYW5zcG9ydF9jb3N0LAogICAgICB5ID0gcHJpY2VfcTUwCiAgICApCiAgKSArCiAgc2NhbGVfeF9jb250aW51b3VzKAogICAgYnJlYWtzID0gYygwLjEsIDAuMjUsIDAuNSwgMC43NSwgMS4wKQogICkKCgpgYGAKCk5vdGUgdGhhdCB0aGUgdHJhbnNwb3J0IGNvc3Qgb2YgMC4yNSBoYWQgYW4gZXJyb3IgaW4gaXRzIGltcGxlbWVudGF0aW9uLiBJbiAwLjI1IHRyYW5zcG9ydCBjb3N0IHBlcmlvZHMsIHN1YmplY3RzIG9ubHkgaGFkIDUgc3VicGVyaW9kcywgbm90IHRoZSAyMCBhbGwgb3RoZXIgcGVyaW9kcyBoYWQuIFRoaXMgbW9zdCBsaWtlbHkgZXhwbGFpbnMgdGhlIG9kZCByZXN1bHQuIAoKCkluIHRoZSB0YWJsZSBiZWxvdyBJIGNvbXBhcmUgYXZlcmFnZSBwcmljZSBiZXR3ZWVuIHRyYW5zcG9ydCBjb3N0IHRyZWF0bWVudHMsIGF0IHRoZSBzZXNzaW9uIGxldmVsLgoKVGhlIHN0YW5kYXJkIGVycm9ycyBhcmUgcHJvYmFibHkgbm90IHRoZSB3YXkgeW91IHdhbnQgdG8gZG8gaXQuIEknbSB1c2luZyBldmVyeSBvYnNlcnZhdGlvbiBmcm9tIGVhY2ggc3VicGVyaW9kIG9mIGVhY2ggcGVyaW9kLiBXZSBwcm9iYWJseSB3YW50IHRvIGNvbXBhcmUgYXZlcmFnZSBwYXlvZmZzIHBlciBwZXJpb2Qgb3IgcGVyIHNlc3Npb24uIEJ1dCBzdGlsbC4uLgoKCgpgYGB7ciwgZWNobyA9IEYsIGV2YWwgPSBULCB0aWR5ID0gVH0KZGYgPSBzZXNEYXQycCAlPiUKICB1bmdyb3VwKCkgJT4lCiAgZ3JvdXBfYnkocGxheWVyLnRyYW5zcG9ydF9jb3N0KSAlPiUKICBtdXRhdGUoCiAgICBwbGF5ZXIucm91bmRfcHJpY2UgPSBwbGF5ZXIucHJpY2UKICApICU+JQogIHN1bW1hcmlzZSgKICAgIG49bigpLAogICAgbWVhbl9wcmljZSA9IG1lYW4ocGxheWVyLnByaWNlKSwgIAogICAgbWVkaWFuX3ByaWNlID0gbWVkaWFuKHBsYXllci5wcmljZSksCiAgICBzZV9wcmljZSA9IHNkKHBsYXllci5wcmljZSkvKG4pXjAuNQogICkgCgprYWJsZSgKICBmb3JtYXQgPSAibWFya2Rvd24iLCAKICBkZiwgIGFsaWduID0gYygiYyIpCiAgIyBjb2wubmFtZXMgPSBjKCIiLCIiLCIiLCJBdmcgVGFzayAxIFJFVCBTY29yZSIsIkF2ZyBUYXNrIDIgUkVUIFNjb3JlIiwiQXZnIFRhc2sgMyBSRVQgU2NvcmUiLCJUb3VybiIsICJTcyIpCikKYGBgCgpQcmljZXMgaW4gdGhlIGB0ID0gMS4wYCB0cmFuc3BvcnQgY29zdCB0cmVhdG1lbnQgd2VyZSBvbiBhdmVyYWdlICQwLjE3NjE5NzkkIG9yICQzOS4xNSRcJSBoaWdoZXIgY29tcGFyZWQgdG8gYHQgPSAwLjFgLiAKCk5vdywgYmVsb3csIHdlIGNhbGN1bGF0ZSBzdGFuZGFyZCBlcnJvciB3aXRoIG1lYW4gcHJpY2VzIGF0IHRoZSBzZXNzaW9uK3BlcmlvZCt0cmFuc3BvcnQgY29zdCBsZXZlbC4gCgpUaGVyZSBhcmUgZmFyIGZld2VyIG9ic2VydmF0aW9ucywgbWFraW5nIG91ciBzdGFuZGFyZCBlcnJvciBtdWNoIGxhcmdlci4gSG93ZXZlciwgc3RpbGwsIHRoZSB2ZXJ5IGxvdyB0cmFuc3BvcnQgY29zdCBhcmUgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgZnJvbSB0aGUgdHdvIHRyYW5zcG9ydCBjb3N0cyBpbiB0aGUgaGlnaCByYW5nZS4gCgpgYGB7ciwgZWNobyA9IEYsIGV2YWwgPSBULCB0aWR5ID0gVH0KZGYgPSBzZXNEYXQycCAlPiUKICB1bmdyb3VwKCkgJT4lCiAgZ3JvdXBfYnkoc2Vzc2lvbi5jb2RlLCBwbGF5ZXIudHJhbnNwb3J0X2Nvc3QsIHBsYXllci5wZXJpb2RfbnVtYmVyKSAlPiUgCiAgbXV0YXRlKAogICAgcGxheWVyLnByaWNlID0gcGxheWVyLnByaWNlIAogICkgJT4lCiAgc3VtbWFyaXNlKAogICAgbj1uKCksCiAgICBtZWFuX3ByaWNlID0gbWVhbihwbGF5ZXIucHJpY2UpLCAgCiAgICBtZWRpYW5fcHJpY2UgPSBtZWRpYW4ocGxheWVyLnByaWNlKSwKICAgIHNlX3ByaWNlID0gc2QocGxheWVyLnByaWNlKS8obileMC41CiAgKQoKZGYgPSBkZiAlPiUKICBncm91cF9ieShwbGF5ZXIudHJhbnNwb3J0X2Nvc3QpICU+JQogIHN1bW1hcmlzZSgKICAgIG49bigpLAogICAgc2VfcHJpY2UgPSBzZChtZWFuX3ByaWNlKS8obileMC41LAogICAgbWVhbl9wcmljZSA9IG1lYW4obWVhbl9wcmljZSkKICApCgprYWJsZSgKICBmb3JtYXQgPSAibWFya2Rvd24iLCAKICBkZiwgIGFsaWduID0gYygiYyIpCiAgIyBjb2wubmFtZXMgPSBjKCIiLCIiLCIiLCJBdmcgVGFzayAxIFJFVCBTY29yZSIsIkF2ZyBUYXNrIDIgUkVUIFNjb3JlIiwiQXZnIFRhc2sgMyBSRVQgU2NvcmUiLCJUb3VybiIsICJTcyIpCikKYGBgCgoKCmBgYHtyLCBlY2hvPUZBTFNFfQpnZ3Bsb3QoCiBzZXNEYXQycCAlPiUKICB1bmdyb3VwKCkgJT4lCiAgZ3JvdXBfYnkoc2Vzc2lvbi5jb2RlLCBwYXJ0aWNpcGFudC5jb2RlLCBwbGF5ZXIudHJhbnNwb3J0X2Nvc3QscGxheWVyLnBlcmlvZF9udW1iZXIpICU+JQogICBzdW1tYXJpc2UoCiAgICAgbWVhbl9wcmljZSA9IG1lYW4ocGxheWVyLnByaWNlKQogICApCikgKwogICAgZ2VvbV92aW9saW4oCiAgICBhZXMoCiAgICAgIHggPSBhcy5mYWN0b3IocGxheWVyLnRyYW5zcG9ydF9jb3N0KSwKICAgICAgeSA9IG1lYW5fcHJpY2UKICAgICksIGFscGhhID0gLjgKICApICsKICBnZW9tX2ppdHRlcigKICAgIGFlcygKICAgICAgeCA9IGFzLmZhY3RvcihwbGF5ZXIudHJhbnNwb3J0X2Nvc3QpLAogICAgICB5ID0gbWVhbl9wcmljZSwKICAgICAgY29sb3IgPSBwbGF5ZXIucGVyaW9kX251bWJlcgogICAgKSwgCiAgICBhbHBoYSA9IC43LAogICAgd2lkdGggPSAuMSwgaGVpZ2h0ID0gMAogICkgKwogIHRoZW1lX2J3KCkKYGBgCgpDb21wYXJpbmcgcHJpY2VzIGluIGB0ID0gMC4xYCBhbmQgYHQgPSAxLjBgIChzZWUgYmVsb3cpLCB0aGVyZSBhcHBlYXJzIHRvIGJlIGEgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBkaWZmZXJlbmNlLiAKCi0gQSB0IHRlc3QgY29tcGFyaW5nIHByaWNlcyBiZXR3ZWVuIG1pbiBhbmQgbWF4IHRyYW5zcG9ydCBjb3N0cy4gUHJpY2VzIGFyZSBhdmVyYWdlIHByaWNlIGF0IHRoZSBzZXNzaW9uLCBwYXJ0aWNpcGFudCwgYW5kIHBlcmlvZCBsZXZlbC4gUC12YWx1ZSAwLjAwMDAyOS4KLSBBIE1XIHJhbmsgc3VtIHRlc3QgY29tcGFyaW5nIHByaWNlcyBiZXR3ZWVuIG1pbiBhbmQgbWF4IHRyYW5zcG9ydCBjb3N0cy4gUHJpY2VzIGFyZSBhdmVyYWdlIHByaWNlIGF0IHRoZSBzZXNzaW9uLCBwYXJ0aWNpcGFudCwgYW5kIHBlcmlvZCBsZXZlbC4gUC12YWx1ZSAwLjAwMDIwNjEuCgpgYGB7ciwgZWNobz1GQUxTRX0KZGYgPSAgc2VzRGF0MnAgJT4lCiAgdW5ncm91cCgpICU+JQogIGdyb3VwX2J5KHNlc3Npb24uY29kZSwgcGFydGljaXBhbnQuY29kZSwgcGxheWVyLnRyYW5zcG9ydF9jb3N0LHBsYXllci5wZXJpb2RfbnVtYmVyKSAlPiUKICAgc3VtbWFyaXNlKAogICAgIG1lYW5fcHJpY2UgPSBtZWFuKHBsYXllci5wcmljZSkKICAgKQp3aXRoKGRmLCB0LnRlc3QobWVhbl9wcmljZVtwbGF5ZXIudHJhbnNwb3J0X2Nvc3QgPT0gMC4xXSwgbWVhbl9wcmljZVtwbGF5ZXIudHJhbnNwb3J0X2Nvc3QgPT0gMS4wXSkpCndpdGgoZGYsIHdpbGNveC50ZXN0KG1lYW5fcHJpY2VbcGxheWVyLnRyYW5zcG9ydF9jb3N0ID09IDAuMV0sIG1lYW5fcHJpY2VbcGxheWVyLnRyYW5zcG9ydF9jb3N0ID09IDEuMF0pKQoKIyMgSG93IG1hbnkgb2JzIGZvciBlYWRjaCB0cmFuc3BvcnQgY29zdCArIHBlcmlvZCBkbyB3ZSBoYXZlPwojIGRmICU+JQojICAgZ3JvdXBfYnkocGxheWVyLnRyYW5zcG9ydF9jb3N0KSAlPiUKIyAgIHN1bW1hcmlzZShuID0gbigpKQpgYGAKCgpTdW1tYXJ5IG9mIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRyYW5zcG9ydCBjb3N0cyBhbmQgcHJpY2VzLiBUaGVyZSBpcyBhIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHByaWNlcyBhbmQgdHJhbnNwb3J0IGNvc3QgdHJlYXRtZW50cy4gSW4gaGlnaGVyIHRyYW5zcG9ydCBjb3N0IHNldHRpbmdzIHN1YmplY3RzIHRlbmRlZCB0byBoYXZlIGhpZ2hlciBwcmljZXMuIAoKCiMjIFByaWNlIFN0aWNraW5lc3MgYW5kIFRyYW5zcG9ydCBDb3N0cwoKQ29uc2lkZXJpbmcgcHJpY2Ugc3RpY2tpbmVzcyBhczogCgotIHN0YW5kYXJkIGRldmlhdGlvbiBvZiBwcmljZXMuCi0gYXZlcmFnZSBjaGFuZ2UgaW4gcHJpY2Ugd2hlbiBwcmljZXMgd2VyZSBjaGFuZ2VkLiAKLSBhdCB0aGUgc2Vzc2lvbiwgcm91bmQsIHBsYXllciBsZXZlbCwgYXZlcmFnZSBudW1iZXIgb2YgdGltZXMgcGxheWVyIGNoYW5nZXMgcHJpY2VzIGJldHdlZW4gcm91bmRzLiAKCgpMb29raW5nIGF0IHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgcHJpY2VzIChiZWxvdyksIHRoZXJlIGRvZXMgbm90IGFwcGVhciB0byBiZSBhIHN0cm9uZyByZWxhdGlvbnNoaXAgYmV0d2VlbiBwcmljZSB2YXJpYXRpb24gYW5kIHRyYW5zcG9ydCBjb3N0LiAKCmBgYHtyLCBlY2hvPUZBTFNFfQoKCmRmID0gIHNlc0RhdDJwICU+JQogIHVuZ3JvdXAoKSAlPiUKICAjIGdyb3VwX2J5KHNlc3Npb24uY29kZSwgcGFydGljaXBhbnQuY29kZSwgcGxheWVyLnRyYW5zcG9ydF9jb3N0LHBsYXllci5wZXJpb2RfbnVtYmVyKSAlPiUKICBncm91cF9ieShzZXNzaW9uLmNvZGUscGFydGljaXBhbnQuY29kZSxwbGF5ZXIucGVyaW9kX251bWJlcikgJT4lCiAgIHN1bW1hcmlzZSgKICAgICBtZWFuX3ByaWNlID0gbWVhbihwbGF5ZXIucHJpY2UpLAogICAgIHByaWNlX3NkID0gc2QocGxheWVyLnByaWNlKQogICApCgoKZ2dwbG90KAogc2VzRGF0MnAgJT4lCiAgdW5ncm91cCgpICU+JQogIGdyb3VwX2J5KHNlc3Npb24uY29kZSwgcGFydGljaXBhbnQuY29kZSwgcGxheWVyLnRyYW5zcG9ydF9jb3N0LHBsYXllci5wZXJpb2RfbnVtYmVyKSAlPiUKICAgc3VtbWFyaXNlKAogICAgIG1lYW5fcHJpY2UgPSBtZWFuKHBsYXllci5wcmljZSksCiAgICAgcHJpY2Vfc2QgPSBzZChwbGF5ZXIucHJpY2UpCiAgICkKKSArCiAgICBnZW9tX3Zpb2xpbigKICAgIGFlcygKICAgICAgeCA9IGFzLmZhY3RvcihwbGF5ZXIudHJhbnNwb3J0X2Nvc3QpLAogICAgICB5ID0gcHJpY2Vfc2QKICAgICksIGFscGhhID0gLjgKICApICsKICBnZW9tX2ppdHRlcigKICAgIGFlcygKICAgICAgeCA9IGFzLmZhY3RvcihwbGF5ZXIudHJhbnNwb3J0X2Nvc3QpLAogICAgICB5ID0gcHJpY2Vfc2QsCiAgICAgIGNvbG9yID0gcGxheWVyLnBlcmlvZF9udW1iZXIKICAgICksIAogICAgYWxwaGEgPSAuNywKICAgIHdpZHRoID0gLjEsIGhlaWdodCA9IDAKICApICsKICB0aGVtZV9idygpICsKICBsYWJzKAogICAgdGl0bGUgPSAiUHJpY2UgU3RhbmRhcmQgRGV2aWF0aW9uIGFuZCBUcmFuc3BvcnQgQ29zdCIsCiAgICBzdWJ0aXRsZSA9ICJPbmUgZG90IGlzIG9uZSBzdWJqZWN0J3MgcHJpY2Ugc2QgaW4gb25lIHBlcmlvZCwgYXQgdGhpcyB0cmFuc3BvcnQgY29zdC4iLAogICAgeSA9ICJQcmljZSBTdGFuZGFyZCBEZXZpYXRpb24iLAogICAgeCA9ICJUcmFuc3BvcnQgQ29zdCIsCiAgICBjb2xvciA9ICJQZXJpb2QgTnVtYmVyIgogICkKYGBgCgoKCgpCZWxvdywgd2UgbG9vayBhdCB0aGUgbWFnbml0dXRkZSBvZiBjaGFuZ2VzIGluIHByaWNlIGJldHdlZW4gc3VicGVyaW9kcy4gT25lIGRvdCByZXByZXNlbnRzIHRoZSBhdmVyYWdlIHByaWNlIGNoYW5nZSAoaW4gYWJzb2x1dGUgdmFsdWUpIGZvciBvbmUgcGxheWVyLCBpbiBvbmUgcGVyaW9kLiBUaGVyZSBkb2VzIG5vdCBhcHBlYXIgdG8gYmUgYSBzaWduaWZpY2FudCByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGlzIG1lYXN1cmUgb2YgcHJpY2Ugc3RpY2tpbmVzcyBhbmQgdHJhbnNwb3J0IGNvc3QgdHJlYXRtZW50LiAKCmBgYHtyLCBlY2hvPUZBTFNFfQoKZGYgPSAgc2VzRGF0MnAgJT4lCiAgdW5ncm91cCgpICU+JQogICMgZ3JvdXBfYnkoc2Vzc2lvbi5jb2RlLCBwYXJ0aWNpcGFudC5jb2RlLCBwbGF5ZXIudHJhbnNwb3J0X2Nvc3QscGxheWVyLnBlcmlvZF9udW1iZXIpICU+JQogIGdyb3VwX2J5KHNlc3Npb24uY29kZSxwYXJ0aWNpcGFudC5jb2RlLHBsYXllci5wZXJpb2RfbnVtYmVyLHBsYXllci50cmFuc3BvcnRfY29zdCkgJT4lCiAgYXJyYW5nZShwYXJ0aWNpcGFudC5fcm91bmRfbnVtYmVyKSAlPiUKICAgbXV0YXRlKAogICAgIHByaWNlX2NoZyA9IHBsYXllci5wcmljZSAtIGxhZyhwbGF5ZXIucHJpY2UpCiAgICkgJT4lCiAgc3VtbWFyaXNlKAogICAgcHJpY2VfbWVhbl9jaGcgPSBtZWFuKHByaWNlX2NoZywgbmEucm0gPSBUKSwKICAgIHByaWNlX21lYW5fY2hnX2FicyA9IG1lYW4oYWJzKHByaWNlX2NoZyksIG5hLnJtID0gVCkKICApCgoKZ2dwbG90KAogIGRmCikgKwogIGdlb21fdmlvbGluKAogICAgYWVzKAogICAgICB4ID0gYXMuZmFjdG9yKHBsYXllci50cmFuc3BvcnRfY29zdCksCiAgICAgIHkgPSBwcmljZV9tZWFuX2NoZ19hYnMKICAgICksIGFscGhhID0gLjgKICApICsKICBnZW9tX2ppdHRlcigKICAgIGFlcygKICAgICAgeCA9IGFzLmZhY3RvcihwbGF5ZXIudHJhbnNwb3J0X2Nvc3QpLAogICAgICB5ID0gcHJpY2VfbWVhbl9jaGdfYWJzLAogICAgICBjb2xvciA9IHBsYXllci5wZXJpb2RfbnVtYmVyCiAgICApLCAKICAgIGFscGhhID0gLjcsCiAgICB3aWR0aCA9IC4xLCBoZWlnaHQgPSAwCiAgKSArCiAgdGhlbWVfYncoKSArCiAgbGFicygKICAgIHRpdGxlID0gIkF2ZXJhZ2UgQ2hhbmdlIGluIFByaWNlIEJldHdlZW4gUm91bmRzIGFuZCBUcmFuc3BvcnQgQ29zdCIsCiAgICBzdWJ0aXRsZSA9ICJPbmUgZG90IGlzIG9uZSBzdWJqZWN0J3MgYXZlcmFnZSBwcmljZSBjaGFuZ2UgKGFic29sdXRlIHZhbHVlKSBpbiBvbmUgcGVyaW9kLCBhdCB0aGlzIHRyYW5zcG9ydCBjb3N0LiIsCiAgICB5ID0gIkF2ZXJhZ2UgQ2hhbmdlIGluIFByaWNlIEJldHdlZW4gUm91bmRzIiwKICAgIHggPSAiVHJhbnNwb3J0IENvc3QiLAogICAgY29sb3IgPSAiUGVyaW9kIE51bWJlciIKICApCmBgYAoKCkJlbG93LCB3ZSBzZWUgdGhlIHBlcmNlbnQgb2YgdGltZXMgc3ViamVjdHMgY2hhbmdlIHByaWNlIGJldHdlZW4gc3VicGVyaW9kcy4gQXMgYSByZW1pbmRlciwgZWFjaCBwZXJpb2QgaXMgZGl2aWRlZCBpbnRvIGEgbnVtYmVyIG9mIHN1YnBlcmlvZHMuIElmIGEgc3ViamVjdCBkb2VzIG5vdGhpbmcgd2l0aCBoaXMgb3IgaGVyIGV4cGVyaW1lbnQgY29udHJvbHMgYmV0d2VlbiBzdWJwZXJpb2RzLCBwcmljZXMgcmVtYWluIHVuY2hhbmdlZC4gU3ViamVjdHMgbXVzdCBhY3RpdmVseSBjbGljayB0byBjaGFuZ2UgcHJpY2VzIGJldHdlZW4gc3VicGVyaW9kcy4gCgpUaGUgcGVyY2VudCBwbG90dGVkIGJlbG93IGluZGljYXRlZCB0aGUgcGVyY2VudCBvZiB0aW1lcyBzdWJqZWN0cyBjaGFuZ2UgdGhlaXIgcHJpY2UgYmV0d2VlbiBwZXJpb2RzLiBBIHNjb3JlIG9mIHplcm8gaW5kaWNhdGVkIHRoZSBzdWJqZWN0IG5ldmVyIGNoYW5nZWQgcHJpY2VzLiBBIHNjb3JlIG9mIDEwMCUgaW5kaWNhdGVzIHRoYXQgcGVyc29uIGNoYW5nZXMgcHJpY2VzIGJldHdlZW4gZXZlcnkgc3VicGVyaW9kLiAKCkFnYWluLCB3ZSBzZWUgd2VhayBldmlkZW5jZSB0aGF0IHByaWNlcyBhcmUgc2xpZ2h0bHkgbW9yZSBzdGlja3kgaW4gaGlnaCB0cmFuc3BvcnQgY29zdCBzZXR0aW5ncy4gCgpgYGB7ciwgZWNobz1GQUxTRX0KCmRmID0gIHNlc0RhdDJwICU+JQogIHVuZ3JvdXAoKSAlPiUKICAjIGdyb3VwX2J5KHNlc3Npb24uY29kZSwgcGFydGljaXBhbnQuY29kZSwgcGxheWVyLnRyYW5zcG9ydF9jb3N0LHBsYXllci5wZXJpb2RfbnVtYmVyKSAlPiUKICBncm91cF9ieShzZXNzaW9uLmNvZGUscGFydGljaXBhbnQuY29kZSxwbGF5ZXIucGVyaW9kX251bWJlcixwbGF5ZXIudHJhbnNwb3J0X2Nvc3QpICU+JQogIGFycmFuZ2UocGFydGljaXBhbnQuX3JvdW5kX251bWJlcikgJT4lCiAgIG11dGF0ZSgKICAgICBwcmljZV9jaGcgPSBhcy5udW1lcmljKCFwbGF5ZXIucHJpY2UgPT0gbGFnKHBsYXllci5wcmljZSkpCiAgICkgJT4lCiAgc3VtbWFyaXNlKAogICAgcHJpY2VfbWVhbl9jaGcgPSBtZWFuKHByaWNlX2NoZywgbmEucm0gPSBUKSAqIDEwMAogICkKCgpnZ3Bsb3QoCiAgZGYKKSArCiAgZ2VvbV92aW9saW4oCiAgICBhZXMoCiAgICAgIHggPSBhcy5mYWN0b3IocGxheWVyLnRyYW5zcG9ydF9jb3N0KSwKICAgICAgeSA9IHByaWNlX21lYW5fY2hnCiAgICApLCAKICAgIGFscGhhID0gLjgKICApICsKICBnZW9tX2ppdHRlcigKICAgIGFlcygKICAgICAgeCA9IGFzLmZhY3RvcihwbGF5ZXIudHJhbnNwb3J0X2Nvc3QpLAogICAgICB5ID0gcHJpY2VfbWVhbl9jaGcsCiAgICAgIGNvbG9yID0gcGxheWVyLnBlcmlvZF9udW1iZXIKICAgICksIAogICAgYWxwaGEgPSAuNywKICAgIHdpZHRoID0gLjEsIGhlaWdodCA9IDAKICApICsKICB0aGVtZV9idygpICsKICBsYWJzKAogICAgdGl0bGUgPSAiRnJlcXVlbmN5IG9mIFByaWNlIENoYW5nZSBhbmQgVHJhbnNwb3J0IENvc3QiLAogICAgc3VidGl0bGUgPSAiT25lIGRvdCBpcyBvbmUgc3ViamVjdCdzIHBlcmNlbnQgb2Ygc3VicGVyaW9kcyBpbiB3aGljaCBwcmljZXMgY2hhbmdlIGluIG9uZSBwZXJpb2QuICIsCiAgICB5ID0gIlBlcmNlbnQgb2YgVW5jaGFuZ2VkIFByaWNlcyIsCiAgICB4ID0gIlRyYW5zcG9ydCBDb3N0IiwKICAgIGNvbG9yID0gIlBlcmlvZCBOdW1iZXIiCiAgKQoKZGYgJT4lCiAgZ3JvdXBfYnkocGxheWVyLnRyYW5zcG9ydF9jb3N0KSAlPiUKICBzdW1tYXJpc2UoCiAgICBuID0gbigpLAogICAgcHJpY2VfY2hyX3ByY3RfbWVhbiA9IG1lYW4ocHJpY2VfbWVhbl9jaGcpLAogICAgcHJpY2VfY2hyX3ByY3RfbWVkaWFuID0gbWVkaWFuKHByaWNlX21lYW5fY2hnKQogICAgCiAgKQpgYGAKCi0tLS0KCiMgRm91ci1QbGF5ZXIgR2FtZQoKIyMgUHJvZml0IGFuZCBUcmFuc3BvcnQgQ29zdAoKS2VlcCBpbiBtaW5kLCB3aGVyZSB0aGUgbWF4IHNjb3JlIG9uZSBjb3VsZCBlYXJuIGluIHRoZSB0d28tcGxheWVyIGdhbWUgaXMgMC41IChpZiBib3RoIHBsYXllcnMgZ28gdG8gdGhlIFBhcmV0byBzdXBlcmlvciBlcXVpbGlicml1bSwgb3IgaW4gdGhlIHVubGlrZWx5IGV2ZW50IHRoYXQgb25lIHBsYXllciBpcyBhdCB0aGUgbWF4IHByaWNlIGFuZCB0aGUgb3RoZXIgdW5kZXJjdXRzIGhpbSBhdCBgcHJpY2UgPSAwLjVgKSwgaW4gdGhlIGZvdXIgcGxheWVyIGdhbWUgdGhlIG1heCBzY29yZSBvbmUgY291bGQgZ2V0LCBJIHRoaW5rLCBpcyAwLjI1LiBUaGlzIHByaWNlIG9jY3VycyB3ZXJlIGFsbCBwbGF5ZXJzIGhhdmUgdGhlIGhpZ2hlc3QgcHJpY2UgcG9zc2libGUuIAoJCkl0IGlzIHBvc3NpYmxlIHRoYXQgc29tZSBwbGF5ZXJzIGRvIGVhcm4gYWJvdmUgMC4yNSBpZiwgaW4gdGhlIHVubGlrZWx5IGV2ZW50IHRoYXQgdGhleSBtYW5hZ2UgdG8gdW5kZXJjdXQgb3RoZXIgcGxheWVycyBmb3IgbWFueSBzdWJwZXJpb2RzIGluIHRoZSB2ZXJ5LWxvdyB0cmFuc3BvcnQgY29zdCB3b3JsZC4KCgoKSG93IHBsYXllciBwcm9maXRzIHJlbGF0ZSB0byB0cmFuc3BvcnQgY29zdCBhdCB0aGUgdmVyeSBoaWdoLCBzZXNzaW9uIGxldmVsPwoKQSB2ZXJ5IGNsZWFyIHN0b3J5LCBJIHRoaW5rLiBUaGUgZmlndXJlIGJlbG93IHBsb3RzIGF2ZXJhZ2UgcGF5b2ZmcyBmb3IgZWFjaCBzZXNzaW9uLiBUaGlzIGF2ZXJhZ2VzIHBheW9mZnMgb3ZlciBhbGwgc3ViamVjdCBpbiBhbGwgcGVyaW9kcyB3aXRoaW4gb25lIHNlc3Npb24uIAoKYGBge3IsIGVjaG89RkFMU0V9CmdncGxvdCgKICBzZXNEYXQ0cCAlPiUKICAgIGdyb3VwX2J5KHNlc3Npb24uY29kZSxwbGF5ZXIudHJhbnNwb3J0X2Nvc3QscGxheWVyLnRyYW5zcG9ydF9jb3N0KSAlPiUKICAgIHN1bW1hcmlzZSgKICAgICAgbWVhbl9wcm9maXQgPSBtZWFuKHBsYXllci5yb3VuZF9wYXlvZmYgKiAyMCkKICAgICkgJT4lCiAgICBmaWx0ZXIoCiAgICAgICFpcy5uYShtZWFuX3Byb2ZpdCkKICAgICkKKSArCiAgZ2VvbV9wb2ludCgKICAgIGFlcygKICAgICAgeCA9IGFzLmZhY3RvcihwbGF5ZXIudHJhbnNwb3J0X2Nvc3QpLAogICAgICB5ID0gbWVhbl9wcm9maXQsCiAgICAgIGNvbG9yID0gcGFzdGUoc2Vzc2lvbi5jb2RlLHBsYXllci50cmFuc3BvcnRfY29zdCkKICAgICkKICApCmBgYAoKCmBgYHtyLCBlY2hvID0gRiwgZXZhbCA9IFQsIHRpZHkgPSBUfQpkZiA9IHNlc0RhdDRwICU+JQogIHVuZ3JvdXAoKSAlPiUKICBncm91cF9ieShwbGF5ZXIudHJhbnNwb3J0X2Nvc3QpICU+JQogIHN1bW1hcmlzZSgKICAgIG49bigpLAogICAgbWVhbl9wcm9maXQgPSBtZWFuKHBsYXllci5yb3VuZF9wYXlvZmYgKiAyMCksICAKICAgIG1lZGlhbl9wcm9maXQgPSBtZWRpYW4ocGxheWVyLnJvdW5kX3BheW9mZiAqIDIwKSwKICAgIHNlX3Byb2ZpdCA9IHNkKHBsYXllci5yb3VuZF9wYXlvZmYgKiAyMCkvKG4pXjAuNQoKICApIAoKa2FibGUoCiAgZm9ybWF0ID0gIm1hcmtkb3duIiwgCiAgZGYsICBhbGlnbiA9IGMoImMiKQogICMgY29sLm5hbWVzID0gYygiIiwiIiwiIiwiQXZnIFRhc2sgMSBSRVQgU2NvcmUiLCJBdmcgVGFzayAyIFJFVCBTY29yZSIsIkF2ZyBUYXNrIDMgUkVUIFNjb3JlIiwiVG91cm4iLCAiU3MiKQopCmBgYAoKVGhlIHN0YW5kYXJkIGVycm9ycyBpbiB0aGUgdGFibGUgYWJvdmUgYXJlIGxpa2VseSB3YXkgdG9vIGdlbmVyb3VzLiBCZWxvdywgdGhlIHNhbWUgdGFibGUsIGJ1dCBvbmx5IGF2ZXJhZ2luZyBvdmVyIHN1YmplY3QrcGVyaW9kK3RyYW5zcG9ydC1jb3N0LiAKCklmIHRoaW5ncyBob2xkIHVwLCB3ZSdkIGdldCBhIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSBiZXR3ZWVuIDAuMSBhbmQgMS4wLCBhbmQgcG9zc2libHkgYmV0d2VlbiBzbWFsbGVyIGluY3JlbWVudHMgb2YgdHJhbnNwb3J0IGNvc3QuIAoKYGBge3IsIGVjaG8gPSBGLCBldmFsID0gVCwgdGlkeSA9IFR9CmRmID0gc2VzRGF0NHAgJT4lCiAgdW5ncm91cCgpICU+JQogIGdyb3VwX2J5KHNlc3Npb24uY29kZSwgcGxheWVyLnRyYW5zcG9ydF9jb3N0LCBwbGF5ZXIucGVyaW9kX251bWJlcikgJT4lIAogIHN1bW1hcmlzZSgKICAgIG49bigpLAogICAgbWVhbl9wcm9maXQgPSBtZWFuKHBsYXllci5yb3VuZF9wYXlvZmYgKiAyMCksICAKICAgIG1lZGlhbl9wcm9maXQgPSBtZWRpYW4ocGxheWVyLnJvdW5kX3BheW9mZiAqIDIwKSwKICAgIHNlX3Byb2ZpdCA9IHNkKHBsYXllci5yb3VuZF9wYXlvZmYgKiAyMCkvKG4pXjAuNQogICkgJT4lCiAgZ3JvdXBfYnkocGxheWVyLnRyYW5zcG9ydF9jb3N0KSAlPiUKICBzdW1tYXJpc2UoCiAgICBuPW4oKSwKICAgIG1lYW5fcHJvZml0XyA9IG1lYW4obWVhbl9wcm9maXQpLCAKICAgIHNlX3Byb2ZpdCA9IHNkKG1lYW5fcHJvZml0KS8obileMC41CiAgKQoKCmthYmxlKAogIGZvcm1hdCA9ICJtYXJrZG93biIsIAogIGRmLCAgYWxpZ24gPSBjKCJjIikKICAjIGNvbC5uYW1lcyA9IGMoIiIsIiIsIiIsIkF2ZyBUYXNrIDEgUkVUIFNjb3JlIiwiQXZnIFRhc2sgMiBSRVQgU2NvcmUiLCJBdmcgVGFzayAzIFJFVCBTY29yZSIsIlRvdXJuIiwgIlNzIikKKQpgYGAKCgpOb3csIGxvb2tpbmcgYXQgdGhlIHZlcnkgZ3JhbnVsYXIgc3ViamVjdCwgcGVyaW9kIGxldmVsLCAKCmBgYHtyLCBlY2hvPUZBTFNFfQpnZ3Bsb3QoCiAgc2VzRGF0NHAgJT4lCiAgICBncm91cF9ieShzZXNzaW9uLmNvZGUscGxheWVyLnRyYW5zcG9ydF9jb3N0KSAlPiUKICAgIGdyb3VwX2J5KHNlc3Npb24uY29kZSwgcGFydGljaXBhbnQuY29kZSwgcGxheWVyLnRyYW5zcG9ydF9jb3N0LHBsYXllci5wZXJpb2RfbnVtYmVyKSAlPiUgCiAgICBzdW1tYXJpc2UoCiAgICAgIG1lYW5fcHJvZml0ID0gbWVhbihwbGF5ZXIucm91bmRfcGF5b2ZmICogbWF4KHN1YnNlc3Npb24ucm91bmRfbnVtYmVyKSkKICAgICkgJT4lCiAgICBmaWx0ZXIoCiAgICAgICFpcy5uYShtZWFuX3Byb2ZpdCkKICAgICkKKSArCiAgICBnZW9tX3Zpb2xpbigKICAgIGFlcygKICAgICAgeCA9IGFzLmZhY3RvcihwbGF5ZXIudHJhbnNwb3J0X2Nvc3QpLAogICAgICB5ID0gbWVhbl9wcm9maXQKICAgICksIGFscGhhID0gLjMKICApICsKICBnZW9tX2ppdHRlcigKICAgIGFlcygKICAgICAgeCA9IGFzLmZhY3RvcihwbGF5ZXIudHJhbnNwb3J0X2Nvc3QpLAogICAgICB5ID0gbWVhbl9wcm9maXQsCiAgICAgIGNvbG9yID0gcGxheWVyLnBlcmlvZF9udW1iZXIKICAgICksIGFscGhhID0gLjcKICApCmBgYAoKTG9va2luZyBtb3JlIGNsb3NlbHkgYXQgdGhlIGRpc3RyaWJ1dGlvbnMsIChiZWxvdykgd2Ugc2VlOwoKLSBiYXNpY2FsbHksIHRoZSBgdCA9IDAuMWAgd2FzIHByb2ZpdGxlc3MgZm9yIHN1YmplY3RzLiAKCi0gdGhlIGB0ID0gMC4yNWAgd29ybGQgd2FzIHByZXR0eSBjbG9zZSB0byB1bnByb2ZpdGFibGUuIAoKLSB0aGUgYHQgPSAwLjc1YCBhbmQgYHQgPSAxLjBgIHdvcmxkcyB3ZXJlIGNvbnNpc3RlbnRseSBpbiB0aGUgcHJvZml0YWJsZSByYW5nZS4gCgpUaGUgZGlzdHJpYnV0aW9ucyBoZXJlIGFyZSBkZXJpdmVkIGZyb20gYSBwbGF5ZXIncyBmaW5hbCBzY29yZSBpbiB0aGUgcGVyaW9kLiAKCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTMuNSwgZmlnLndpZHRoPTh9CmdncGxvdCgKICBzZXNEYXQ0cCAlPiUKICAgIGdyb3VwX2J5KHNlc3Npb24uY29kZSxwbGF5ZXIudHJhbnNwb3J0X2Nvc3QpICU+JQogICAgZ3JvdXBfYnkoc2Vzc2lvbi5jb2RlLCBwYXJ0aWNpcGFudC5jb2RlLCBwbGF5ZXIudHJhbnNwb3J0X2Nvc3QscGxheWVyLnBlcmlvZF9udW1iZXIpICU+JSAKICAgIHN1bW1hcmlzZSgKICAgICAgcGF5b2ZmID0gbWVhbihwbGF5ZXIucm91bmRfcGF5b2ZmICogbWF4KHN1YnNlc3Npb24ucm91bmRfbnVtYmVyKSkgCiAgICApCikgKwogICAgZ2VvbV9kZW5zaXR5KAogICAgYWVzKAogICAgICB4ICA9IHBheW9mZiwKICAgICAgY29sb3VyID0gYXMuZmFjdG9yKHBsYXllci5wZXJpb2RfbnVtYmVyKSwKICAgICAgZmlsbCA9IGFzLmZhY3RvcihwbGF5ZXIucGVyaW9kX251bWJlcikKICAgICksIGFscGhhID0gLjIKICApICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpICsgCiAgZmFjZXRfZ3JpZCguIH5wbGF5ZXIudHJhbnNwb3J0X2Nvc3QpIAoKYGBgCgpCZWxvdywgbG9va2luZyBhdCB0aGVzZSBkaXN0cnVidGlvbnMgd2l0aCBhIG1vcmUgZ3JhbmR1bGFyIHZpZXcuIEhlcmUgd2UgbG9vayBhdCBhbGwgb2JzZXJ2YXRpb25zIG9mIGFsbCBwYXlvZmZzLCBpbmNsdWRpbmcgdGhvc2Ugd2l0aGluIGEgcGVyaW9kLiAKCkl0IG1vcmUgY2xlYXJseSBzaG93cyB0aGF0IGluIGFsbCBvZiB0aGVzZSB3b3JsZHMsIHBlb3BsZSBkbyBzcGVuZCBhIGxvdCBvZiB0aW1lIGF0IHplcm8gcGF5b2Zmcy4gCgpJIGRyb3AgYHQgPSAwLjFgIGJlY2F1c2UgdGhleSBhcmUgYmFzaWNhbGx5IGFsbCBhdCB6ZXJvIHBheW9mZnMuIAoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9My41LCBmaWcud2lkdGg9OH0KZ2dwbG90KAogc2VzRGF0NHAgJT4lCiAgdW5ncm91cCgpICU+JQogIGdyb3VwX2J5KHNlc3Npb24uY29kZSwgcGFydGljaXBhbnQuY29kZSwgcGxheWVyLnRyYW5zcG9ydF9jb3N0LHBsYXllci5wZXJpb2RfbnVtYmVyKSAlPiUKICBtdXRhdGUoCiAgICBwYXlvZmYgPSBwbGF5ZXIucm91bmRfcGF5b2ZmICogbWF4KHN1YnNlc3Npb24ucm91bmRfbnVtYmVyKSAjZGVhbCB3aXRoIGYnaW5nIHQ9MC4yNS4uLgogICkgJT4lCiAgIGZpbHRlcihwbGF5ZXIudHJhbnNwb3J0X2Nvc3QgPiAwLjEpCikgKwogICAgZ2VvbV9kZW5zaXR5KAogICAgYWVzKAogICAgICB4ICA9IHBheW9mZiwKICAgICAgY29sb3VyID0gYXMuZmFjdG9yKHBsYXllci5wZXJpb2RfbnVtYmVyKSwKICAgICAgZmlsbCA9IGFzLmZhY3RvcihwbGF5ZXIucGVyaW9kX251bWJlcikKICAgICksIGFscGhhID0gLjIKICApICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInRvcCIpICsgCiAgZmFjZXRfZ3JpZCguIH5wbGF5ZXIudHJhbnNwb3J0X2Nvc3QpICsKICBjb29yZF9jYXJ0ZXNpYW4oeGxpbT1jKDAsIC4yNSkpCgpgYGAKCiMjIFByaWNlcyBhbmQgVHJhbnNwb3J0IENvc3RzCgpIb3cgZG8gcHJpY2VzIHJlbGF0ZWQgdG8gdHJhbnNwb3J0IGNvc3Q/IApIb3cgZG9lcyBwcmljZSBzdGlja2luZXNzIHJlbGF0ZWQgdG8gdHJhbnNwb3J0IGNvc3Q/CgoKVGhlIGZpZ3VyZSBiZWxvdyBwbG90cyBwcmljZXMgZm9yIGVhY2ggc2Vzc2lvbi4gVGhpcyBhdmVyYWdlcyBwYXlvZmZzIG92ZXIgYWxsIHN1YmplY3QgaW4gYWxsIHBlcmlvZHMgd2l0aGluIG9uZSB0cmFuc3BvcnQgY29zdCB0cmVhdG1lbnQgZ3JvdXAuIAoKLSBUaGUgdmlvbGVuIHNob3dzIHRoZSBkaXN0cmlidXRpb24gb2YgcHJpY2VzIHdpdGhpbiB0aGF0IHRyYW5zcG9ydCBjb3N0IHRyZWF0bWVudCBncm91cC4gCi0gVGhlIGdyZXkgcmliYmVuIHNob3dzIHRoZSBmaXJzdCBhbmQgdGhpcmQgcXVhcnRpbGUgb2YgcHJpY2VzLCB0aGF0IGlzLCA1MFwlIG9mIGFsbCBwcmljZXMgc2VsZWN0ZWQgYnkgc3ViamVjdHMgaW4gdGhlIHRyZWF0bWVudCBncm91cCB3ZXJlIHdpdGhpbiB0aGUgcmliYmluLiAKLSBUaGUgbGluZSBzaG93cyB0aGUgbWVkaWFuIGZvciBlYWNoIHRyYW5zcG9ydCBjb3N0IHRyZWF0bWVudCBncm91cC4gCgpXZSBzZWUgYSBnZW5lcmFsbHkgcG9zaXRpdmUgcmVsYXRpb25zaGlwIGJldHdlZW4gcHJpY2VzIGFuZCB0cmFuc3BvcnQgY29zdHMuIAoKYGBge3IsIGVjaG89RkFMU0V9CgpnZ3Bsb3QoCiAgc2VzRGF0NHAgJT4lCiAgICBncm91cF9ieShwbGF5ZXIudHJhbnNwb3J0X2Nvc3QpICU+JQogICAgc3VtbWFyaXNlKAogICAgICBwcmljZV9xNzUgPSBxdWFudGlsZShwbGF5ZXIucHJpY2UsIDAuNzUpLAogICAgICBwcmljZV9xNTAgPSBxdWFudGlsZShwbGF5ZXIucHJpY2UsIDAuNSksCiAgICAgIHByaWNlX3EyNSA9IHF1YW50aWxlKHBsYXllci5wcmljZSwgMC4yNSksCiAgICAgIG1lYW5fcHJpY2UgPSBtZWFuKHBsYXllci5wcmljZSkKICAgICkgCikgKwogICAgZ2VvbV92aW9saW4oCiAgICBkYXRhID0gc2VzRGF0MnAsCiAgICBhZXMoCiAgICAgIHggPSBwbGF5ZXIudHJhbnNwb3J0X2Nvc3QsCiAgICAgIHkgPSBwbGF5ZXIucHJpY2UsCiAgICAgIGdyb3VwID0gcGxheWVyLnRyYW5zcG9ydF9jb3N0CiAgICApLAogICAgYWxwaGEgPSAwLjMsCiAgICBjb2xvciA9ICJncmV5NzAiCiAgKSArCiAgZ2VvbV9yaWJib24oCiAgICBhZXMoCiAgICAgIHggPSAocGxheWVyLnRyYW5zcG9ydF9jb3N0KSwKICAgICAgeW1heCA9IHByaWNlX3E3NSwKICAgICAgeW1pbiA9IHByaWNlX3EyNQogICAgKSwKICAgIGFscGhhID0gLjIKICApICsKICBnZW9tX2xpbmUoCiAgICBhZXMoCiAgICAgIHggPSBwbGF5ZXIudHJhbnNwb3J0X2Nvc3QsCiAgICAgIHkgPSBwcmljZV9xNTAKICAgICkKICApICsKICBzY2FsZV94X2NvbnRpbnVvdXMoCiAgICBicmVha3MgPSBjKDAuMSwgMC4yNSwgMC41LCAwLjc1LCAxLjApCiAgKQoKCmBgYAoKCkluIHRoZSB0YWJsZSBiZWxvdyBJIGNvbXBhcmUgYXZlcmFnZSBwcmljZSBiZXR3ZWVuIHRyYW5zcG9ydCBjb3N0IHRyZWF0bWVudHMsIGF0IHRoZSBzZXNzaW9uIGxldmVsLgoKVGhlIHN0YW5kYXJkIGVycm9ycyBhcmUgcHJvYmFibHkgbm90IHRoZSB3YXkgeW91IHdhbnQgdG8gZG8gaXQuIEknbSB1c2luZyBldmVyeSBvYnNlcnZhdGlvbiBmcm9tIGVhY2ggc3VicGVyaW9kIG9mIGVhY2ggcGVyaW9kLiBXZSBwcm9iYWJseSB3YW50IHRvIGNvbXBhcmUgYXZlcmFnZSBwYXlvZmZzIHBlciBwZXJpb2Qgb3IgcGVyIHNlc3Npb24uIEJ1dCBzdGlsbC4uLgoKCgpgYGB7ciwgZWNobyA9IEYsIGV2YWwgPSBULCB0aWR5ID0gVH0KZGYgPSBzZXNEYXQ0cCAlPiUKICB1bmdyb3VwKCkgJT4lCiAgZ3JvdXBfYnkocGxheWVyLnRyYW5zcG9ydF9jb3N0KSAlPiUKICBtdXRhdGUoCiAgICBwbGF5ZXIucm91bmRfcHJpY2UgPSBwbGF5ZXIucHJpY2UKICApICU+JQogIHN1bW1hcmlzZSgKICAgIG49bigpLAogICAgbWVhbl9wcmljZSA9IG1lYW4ocGxheWVyLnByaWNlKSwgIAogICAgbWVkaWFuX3ByaWNlID0gbWVkaWFuKHBsYXllci5wcmljZSksCiAgICBzZV9wcmljZSA9IHNkKHBsYXllci5wcmljZSkvKG4pXjAuNQogICkgCgprYWJsZSgKICBmb3JtYXQgPSAibWFya2Rvd24iLCAKICBkZiwgIGFsaWduID0gYygiYyIpCiAgIyBjb2wubmFtZXMgPSBjKCIiLCIiLCIiLCJBdmcgVGFzayAxIFJFVCBTY29yZSIsIkF2ZyBUYXNrIDIgUkVUIFNjb3JlIiwiQXZnIFRhc2sgMyBSRVQgU2NvcmUiLCJUb3VybiIsICJTcyIpCikKYGBgCgpQcmljZXMgaW4gdGhlIGB0ID0gMS4wYCB0cmFuc3BvcnQgY29zdCB0cmVhdG1lbnQgd2VyZSBvbiBhdmVyYWdlICQwLjE0NiQgb3IgJDg1LjgyJFwlIGhpZ2hlciBjb21wYXJlZCB0byBgdCA9IDAuMWAuIAoKTm93LCBiZWxvdywgd2UgY2FsY3VsYXRlIHN0YW5kYXJkIGVycm9yIHdpdGggbWVhbiBwcmljZXMgYXQgdGhlIHNlc3Npb24rcGVyaW9kK3RyYW5zcG9ydCBjb3N0IGxldmVsLiAKClRoZXJlIGFyZSBmYXIgZmV3ZXIgb2JzZXJ2YXRpb25zLCBtYWtpbmcgb3VyIHN0YW5kYXJkIGVycm9yIG11Y2ggbGFyZ2VyLiBIb3dldmVyLCBzdGlsbCwgdGhlIHZlcnkgbG93IHRyYW5zcG9ydCBjb3N0IGFyZSBzaWduaWZpY2FudGx5IGRpZmZlcmVudCBmcm9tIHRoZSB0d28gdHJhbnNwb3J0IGNvc3RzIGluIHRoZSBoaWdoIHJhbmdlLiAKCmBgYHtyLCBlY2hvID0gRiwgZXZhbCA9IFQsIHRpZHkgPSBUfQpkZiA9IHNlc0RhdDRwICU+JQogIHVuZ3JvdXAoKSAlPiUKICBncm91cF9ieShzZXNzaW9uLmNvZGUsIHBsYXllci50cmFuc3BvcnRfY29zdCwgcGxheWVyLnBlcmlvZF9udW1iZXIpICU+JSAKICBtdXRhdGUoCiAgICBwbGF5ZXIucHJpY2UgPSBwbGF5ZXIucHJpY2UgCiAgKSAlPiUKICBzdW1tYXJpc2UoCiAgICBuPW4oKSwKICAgIG1lYW5fcHJpY2UgPSBtZWFuKHBsYXllci5wcmljZSksICAKICAgIG1lZGlhbl9wcmljZSA9IG1lZGlhbihwbGF5ZXIucHJpY2UpLAogICAgc2VfcHJpY2UgPSBzZChwbGF5ZXIucHJpY2UpLyhuKV4wLjUKICApCgpkZiA9IGRmICU+JQogIGdyb3VwX2J5KHBsYXllci50cmFuc3BvcnRfY29zdCkgJT4lCiAgc3VtbWFyaXNlKAogICAgbj1uKCksCiAgICBzZV9wcmljZSA9IHNkKG1lYW5fcHJpY2UpLyhuKV4wLjUsCiAgICBtZWFuX3ByaWNlID0gbWVhbihtZWFuX3ByaWNlKQogICkKCmthYmxlKAogIGZvcm1hdCA9ICJtYXJrZG93biIsIAogIGRmLCAgYWxpZ24gPSBjKCJjIikKICAjIGNvbC5uYW1lcyA9IGMoIiIsIiIsIiIsIkF2ZyBUYXNrIDEgUkVUIFNjb3JlIiwiQXZnIFRhc2sgMiBSRVQgU2NvcmUiLCJBdmcgVGFzayAzIFJFVCBTY29yZSIsIlRvdXJuIiwgIlNzIikKKQpgYGAKCgoKYGBge3IsIGVjaG89RkFMU0V9CmdncGxvdCgKIHNlc0RhdDRwICU+JQogIHVuZ3JvdXAoKSAlPiUKICBncm91cF9ieShzZXNzaW9uLmNvZGUsIHBhcnRpY2lwYW50LmNvZGUsIHBsYXllci50cmFuc3BvcnRfY29zdCxwbGF5ZXIucGVyaW9kX251bWJlcikgJT4lCiAgIHN1bW1hcmlzZSgKICAgICBtZWFuX3ByaWNlID0gbWVhbihwbGF5ZXIucHJpY2UpCiAgICkKKSArCiAgICBnZW9tX3Zpb2xpbigKICAgIGFlcygKICAgICAgeCA9IGFzLmZhY3RvcihwbGF5ZXIudHJhbnNwb3J0X2Nvc3QpLAogICAgICB5ID0gbWVhbl9wcmljZQogICAgKSwgYWxwaGEgPSAuOAogICkgKwogIGdlb21faml0dGVyKAogICAgYWVzKAogICAgICB4ID0gYXMuZmFjdG9yKHBsYXllci50cmFuc3BvcnRfY29zdCksCiAgICAgIHkgPSBtZWFuX3ByaWNlLAogICAgICBjb2xvciA9IHBsYXllci5wZXJpb2RfbnVtYmVyCiAgICApLCAKICAgIGFscGhhID0gLjcsCiAgICB3aWR0aCA9IC4xLCBoZWlnaHQgPSAwCiAgKSArCiAgdGhlbWVfYncoKQpgYGAKCkNvbXBhcmluZyBwcmljZXMgaW4gYHQgPSAwLjFgIGFuZCBgdCA9IDEuMGAgKHNlZSBiZWxvdyksIHRoZXJlIGFwcGVhcnMgdG8gYmUgYSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IGRpZmZlcmVuY2UuIAoKLSBBIHQgdGVzdCBjb21wYXJpbmcgcHJpY2VzIGJldHdlZW4gbWluIGFuZCBtYXggdHJhbnNwb3J0IGNvc3RzLiBQcmljZXMgYXJlIGF2ZXJhZ2UgcHJpY2UgYXQgdGhlIHNlc3Npb24sIHBhcnRpY2lwYW50LCBhbmQgcGVyaW9kIGxldmVsLiBQLXZhbHVlIDAuMDAwMDAwMjI4NS4KLSBBIE1XIHJhbmsgc3VtIHRlc3QgY29tcGFyaW5nIHByaWNlcyBiZXR3ZWVuIG1pbiBhbmQgbWF4IHRyYW5zcG9ydCBjb3N0cy4gUHJpY2VzIGFyZSBhdmVyYWdlIHByaWNlIGF0IHRoZSBzZXNzaW9uLCBwYXJ0aWNpcGFudCwgYW5kIHBlcmlvZCBsZXZlbC4gUC12YWx1ZSA0LjQ1OGUtMTAuCgpgYGB7ciwgZWNobz1GQUxTRX0KZGYgPSAgc2VzRGF0NHAgJT4lCiAgdW5ncm91cCgpICU+JQogIGdyb3VwX2J5KHNlc3Npb24uY29kZSwgcGFydGljaXBhbnQuY29kZSwgcGxheWVyLnRyYW5zcG9ydF9jb3N0LHBsYXllci5wZXJpb2RfbnVtYmVyKSAlPiUKICAgc3VtbWFyaXNlKAogICAgIG1lYW5fcHJpY2UgPSBtZWFuKHBsYXllci5wcmljZSkKICAgKQp3aXRoKGRmLCB0LnRlc3QobWVhbl9wcmljZVtwbGF5ZXIudHJhbnNwb3J0X2Nvc3QgPT0gMC4xXSwgbWVhbl9wcmljZVtwbGF5ZXIudHJhbnNwb3J0X2Nvc3QgPT0gMS4wXSkpCndpdGgoZGYsIHdpbGNveC50ZXN0KG1lYW5fcHJpY2VbcGxheWVyLnRyYW5zcG9ydF9jb3N0ID09IDAuMV0sIG1lYW5fcHJpY2VbcGxheWVyLnRyYW5zcG9ydF9jb3N0ID09IDEuMF0pKQoKIyMgSG93IG1hbnkgb2JzIGZvciBlYWRjaCB0cmFuc3BvcnQgY29zdCArIHBlcmlvZCBkbyB3ZSBoYXZlPwpkZiAlPiUKICBncm91cF9ieShwbGF5ZXIudHJhbnNwb3J0X2Nvc3QpICU+JQogIHN1bW1hcmlzZShuID0gbigpKQpgYGAKCgpTdW1tYXJ5IG9mIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRyYW5zcG9ydCBjb3N0cyBhbmQgcHJpY2VzLiBUaGVyZSBpcyBhIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHByaWNlcyBhbmQgdHJhbnNwb3J0IGNvc3QgdHJlYXRtZW50cy4gSW4gaGlnaGVyIHRyYW5zcG9ydCBjb3N0IHNldHRpbmdzIHN1YmplY3RzIHRlbmRlZCB0byBoYXZlIGhpZ2hlciBwcmljZXMuIAoKCgoKIyMgUHJpY2UgU3RpY2tpbmVzcyBhbmQgVHJhbnNwb3J0IENvc3RzCgpDb25zaWRlcmluZyBwcmljZSBzdGlja2luZXNzIGFzOiAKCi0gc3RhbmRhcmQgZGV2aWF0aW9uIG9mIHByaWNlcy4KLSBhdmVyYWdlIGNoYW5nZSBpbiBwcmljZSB3aGVuIHByaWNlcyB3ZXJlIGNoYW5nZWQuIAotIGF0IHRoZSBzZXNzaW9uLCByb3VuZCwgcGxheWVyIGxldmVsLCBhdmVyYWdlIG51bWJlciBvZiB0aW1lcyBwbGF5ZXIgY2hhbmdlcyBwcmljZXMgYmV0d2VlbiByb3VuZHMuIAoKCkxvb2tpbmcgYXQgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiBwcmljZXMgKGJlbG93KSwgdGhlcmUgZG9lcyBub3QgYXBwZWFyIHRvIGJlIGEgc3Ryb25nIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHByaWNlIHZhcmlhdGlvbiBhbmQgdHJhbnNwb3J0IGNvc3QuIAoKYGBge3IsIGVjaG89RkFMU0V9CgoKZGYgPSAgc2VzRGF0NHAgJT4lCiAgdW5ncm91cCgpICU+JQogICMgZ3JvdXBfYnkoc2Vzc2lvbi5jb2RlLCBwYXJ0aWNpcGFudC5jb2RlLCBwbGF5ZXIudHJhbnNwb3J0X2Nvc3QscGxheWVyLnBlcmlvZF9udW1iZXIpICU+JQogIGdyb3VwX2J5KHNlc3Npb24uY29kZSxwYXJ0aWNpcGFudC5jb2RlLHBsYXllci5wZXJpb2RfbnVtYmVyKSAlPiUKICAgc3VtbWFyaXNlKAogICAgIG1lYW5fcHJpY2UgPSBtZWFuKHBsYXllci5wcmljZSksCiAgICAgcHJpY2Vfc2QgPSBzZChwbGF5ZXIucHJpY2UpCiAgICkKCgpnZ3Bsb3QoCiBzZXNEYXQycCAlPiUKICB1bmdyb3VwKCkgJT4lCiAgZ3JvdXBfYnkoc2Vzc2lvbi5jb2RlLCBwYXJ0aWNpcGFudC5jb2RlLCBwbGF5ZXIudHJhbnNwb3J0X2Nvc3QscGxheWVyLnBlcmlvZF9udW1iZXIpICU+JQogICBzdW1tYXJpc2UoCiAgICAgbWVhbl9wcmljZSA9IG1lYW4ocGxheWVyLnByaWNlKSwKICAgICBwcmljZV9zZCA9IHNkKHBsYXllci5wcmljZSkKICAgKQopICsKICAgIGdlb21fdmlvbGluKAogICAgYWVzKAogICAgICB4ID0gYXMuZmFjdG9yKHBsYXllci50cmFuc3BvcnRfY29zdCksCiAgICAgIHkgPSBwcmljZV9zZAogICAgKSwgYWxwaGEgPSAuOAogICkgKwogIGdlb21faml0dGVyKAogICAgYWVzKAogICAgICB4ID0gYXMuZmFjdG9yKHBsYXllci50cmFuc3BvcnRfY29zdCksCiAgICAgIHkgPSBwcmljZV9zZCwKICAgICAgY29sb3IgPSBwbGF5ZXIucGVyaW9kX251bWJlcgogICAgKSwgCiAgICBhbHBoYSA9IC43LAogICAgd2lkdGggPSAuMSwgaGVpZ2h0ID0gMAogICkgKwogIHRoZW1lX2J3KCkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJQcmljZSBTdGFuZGFyZCBEZXZpYXRpb24gYW5kIFRyYW5zcG9ydCBDb3N0IiwKICAgIHN1YnRpdGxlID0gIk9uZSBkb3QgaXMgb25lIHN1YmplY3QncyBwcmljZSBzZCBpbiBvbmUgcGVyaW9kLCBhdCB0aGlzIHRyYW5zcG9ydCBjb3N0LiIsCiAgICB5ID0gIlByaWNlIFN0YW5kYXJkIERldmlhdGlvbiIsCiAgICB4ID0gIlRyYW5zcG9ydCBDb3N0IiwKICAgIGNvbG9yID0gIlBlcmlvZCBOdW1iZXIiCiAgKQpgYGAKCgoKCkJlbG93LCB3ZSBsb29rIGF0IHRoZSBtYWduaXR1dGRlIG9mIGNoYW5nZXMgaW4gcHJpY2UgYmV0d2VlbiBzdWJwZXJpb2RzLiBPbmUgZG90IHJlcHJlc2VudHMgdGhlIGF2ZXJhZ2UgcHJpY2UgY2hhbmdlIChpbiBhYnNvbHV0ZSB2YWx1ZSkgZm9yIG9uZSBwbGF5ZXIsIGluIG9uZSBwZXJpb2QuIFRoZXJlIGRvZXMgbm90IGFwcGVhciB0byBiZSBhIHNpZ25pZmljYW50IHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoaXMgbWVhc3VyZSBvZiBwcmljZSBzdGlja2luZXNzIGFuZCB0cmFuc3BvcnQgY29zdCB0cmVhdG1lbnQuIAoKYGBge3IsIGVjaG89RkFMU0V9CgpkZiA9ICBzZXNEYXQ0cCAlPiUKICB1bmdyb3VwKCkgJT4lCiAgIyBncm91cF9ieShzZXNzaW9uLmNvZGUsIHBhcnRpY2lwYW50LmNvZGUsIHBsYXllci50cmFuc3BvcnRfY29zdCxwbGF5ZXIucGVyaW9kX251bWJlcikgJT4lCiAgZ3JvdXBfYnkoc2Vzc2lvbi5jb2RlLHBhcnRpY2lwYW50LmNvZGUscGxheWVyLnBlcmlvZF9udW1iZXIscGxheWVyLnRyYW5zcG9ydF9jb3N0KSAlPiUKICBhcnJhbmdlKHBhcnRpY2lwYW50Ll9yb3VuZF9udW1iZXIpICU+JQogICBtdXRhdGUoCiAgICAgcHJpY2VfY2hnID0gcGxheWVyLnByaWNlIC0gbGFnKHBsYXllci5wcmljZSkKICAgKSAlPiUKICBzdW1tYXJpc2UoCiAgICBwcmljZV9tZWFuX2NoZyA9IG1lYW4ocHJpY2VfY2hnLCBuYS5ybSA9IFQpLAogICAgcHJpY2VfbWVhbl9jaGdfYWJzID0gbWVhbihhYnMocHJpY2VfY2hnKSwgbmEucm0gPSBUKQogICkKCgpnZ3Bsb3QoCiAgZGYKKSArCiAgZ2VvbV92aW9saW4oCiAgICBhZXMoCiAgICAgIHggPSBhcy5mYWN0b3IocGxheWVyLnRyYW5zcG9ydF9jb3N0KSwKICAgICAgeSA9IHByaWNlX21lYW5fY2hnX2FicwogICAgKSwgYWxwaGEgPSAuOAogICkgKwogIGdlb21faml0dGVyKAogICAgYWVzKAogICAgICB4ID0gYXMuZmFjdG9yKHBsYXllci50cmFuc3BvcnRfY29zdCksCiAgICAgIHkgPSBwcmljZV9tZWFuX2NoZ19hYnMsCiAgICAgIGNvbG9yID0gcGxheWVyLnBlcmlvZF9udW1iZXIKICAgICksIAogICAgYWxwaGEgPSAuNywKICAgIHdpZHRoID0gLjEsIGhlaWdodCA9IDAKICApICsKICB0aGVtZV9idygpICsKICBsYWJzKAogICAgdGl0bGUgPSAiQXZlcmFnZSBDaGFuZ2UgaW4gUHJpY2UgQmV0d2VlbiBSb3VuZHMgYW5kIFRyYW5zcG9ydCBDb3N0IiwKICAgIHN1YnRpdGxlID0gIk9uZSBkb3QgaXMgb25lIHN1YmplY3QncyBhdmVyYWdlIHByaWNlIGNoYW5nZSAoYWJzb2x1dGUgdmFsdWUpIGluIG9uZSBwZXJpb2QsIGF0IHRoaXMgdHJhbnNwb3J0IGNvc3QuIiwKICAgIHkgPSAiQXZlcmFnZSBDaGFuZ2UgaW4gUHJpY2UgQmV0d2VlbiBSb3VuZHMiLAogICAgeCA9ICJUcmFuc3BvcnQgQ29zdCIsCiAgICBjb2xvciA9ICJQZXJpb2QgTnVtYmVyIgogICkKCmRmICU+JQogIGdyb3VwX2J5KHBsYXllci50cmFuc3BvcnRfY29zdCkgJT4lCiAgc3VtbWFyaXNlKAogICAgbiA9IG4oKSwKICAgIHByaWNlX21lYW5fY2hnX2Fic19zZCA9IHNkKHByaWNlX21lYW5fY2hnX2FicyksCiAgICBwcmljZV9tZWFuX2NoZ19hYnMgPSBtZWFuKHByaWNlX21lYW5fY2hnX2FicykKICApCgpgYGAKCgpCZWxvdywgd2Ugc2VlIHRoZSBwZXJjZW50IG9mIHRpbWVzIHN1YmplY3RzIGNoYW5nZSBwcmljZSBiZXR3ZWVuIHN1YnBlcmlvZHMuIEFzIGEgcmVtaW5kZXIsIGVhY2ggcGVyaW9kIGlzIGRpdmlkZWQgaW50byBhIG51bWJlciBvZiBzdWJwZXJpb2RzLiBJZiBhIHN1YmplY3QgZG9lcyBub3RoaW5nIHdpdGggaGlzIG9yIGhlciBleHBlcmltZW50IGNvbnRyb2xzIGJldHdlZW4gc3VicGVyaW9kcywgcHJpY2VzIHJlbWFpbiB1bmNoYW5nZWQuIFN1YmplY3RzIG11c3QgYWN0aXZlbHkgY2xpY2sgdG8gY2hhbmdlIHByaWNlcyBiZXR3ZWVuIHN1YnBlcmlvZHMuIAoKVGhlIHBlcmNlbnQgcGxvdHRlZCBiZWxvdyBpbmRpY2F0ZWQgdGhlIHBlcmNlbnQgb2YgdGltZXMgc3ViamVjdHMgY2hhbmdlIHRoZWlyIHByaWNlIGJldHdlZW4gcGVyaW9kcy4gQSBzY29yZSBvZiB6ZXJvIGluZGljYXRlZCB0aGUgc3ViamVjdCBuZXZlciBjaGFuZ2VkIHByaWNlcy4gQSBzY29yZSBvZiAkMTAwJFwlIGluZGljYXRlcyB0aGF0IHBlcnNvbiBjaGFuZ2VzIHByaWNlcyBiZXR3ZWVuIGV2ZXJ5IHN1YnBlcmlvZC4gCgpBZ2Fpbiwgd2Ugc2VlIHdlYWsgZXZpZGVuY2UgdGhhdCBwcmljZXMgYXJlIHNsaWdodGx5IG1vcmUgc3RpY2t5IGluIGhpZ2ggdHJhbnNwb3J0IGNvc3Qgc2V0dGluZ3MuIAoKYGBge3IsIGVjaG89RkFMU0V9CgpkZiA9ICBzZXNEYXQ0cCAlPiUKICB1bmdyb3VwKCkgJT4lCiAgIyBncm91cF9ieShzZXNzaW9uLmNvZGUsIHBhcnRpY2lwYW50LmNvZGUsIHBsYXllci50cmFuc3BvcnRfY29zdCxwbGF5ZXIucGVyaW9kX251bWJlcikgJT4lCiAgZ3JvdXBfYnkoc2Vzc2lvbi5jb2RlLHBhcnRpY2lwYW50LmNvZGUscGxheWVyLnBlcmlvZF9udW1iZXIscGxheWVyLnRyYW5zcG9ydF9jb3N0KSAlPiUKICBhcnJhbmdlKHBhcnRpY2lwYW50Ll9yb3VuZF9udW1iZXIpICU+JQogICBtdXRhdGUoCiAgICAgcHJpY2VfY2hnID0gYXMubnVtZXJpYyghcGxheWVyLnByaWNlID09IGxhZyhwbGF5ZXIucHJpY2UpKQogICApICU+JQogIHN1bW1hcmlzZSgKICAgIHByaWNlX21lYW5fY2hnID0gbWVhbihwcmljZV9jaGcsIG5hLnJtID0gVCkgKiAxMDAKICApCgoKZ2dwbG90KAogIGRmCikgKwogIGdlb21fdmlvbGluKAogICAgYWVzKAogICAgICB4ID0gYXMuZmFjdG9yKHBsYXllci50cmFuc3BvcnRfY29zdCksCiAgICAgIHkgPSBwcmljZV9tZWFuX2NoZwogICAgKSwgYWxwaGEgPSAuOAogICkgKwogIGdlb21faml0dGVyKAogICAgYWVzKAogICAgICB4ID0gYXMuZmFjdG9yKHBsYXllci50cmFuc3BvcnRfY29zdCksCiAgICAgIHkgPSBwcmljZV9tZWFuX2NoZywKICAgICAgY29sb3IgPSBwbGF5ZXIucGVyaW9kX251bWJlcgogICAgKSwgCiAgICBhbHBoYSA9IC43LAogICAgd2lkdGggPSAuMSwgaGVpZ2h0ID0gMAogICkgKwogIHRoZW1lX2J3KCkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJGcmVxdWVuY3kgb2YgUHJpY2UgQ2hhbmdlIGFuZCBUcmFuc3BvcnQgQ29zdCIsCiAgICBzdWJ0aXRsZSA9ICJPbmUgZG90IGlzIG9uZSBzdWJqZWN0J3MgcGVyY2VudCBvZiBzdWJwZXJpb2RzIGluIHdoaWNoIHByaWNlcyBjaGFuZ2UgaW4gb25lIHBlcmlvZC4gIiwKICAgIHkgPSAiUGVyY2VudCBvZiBVbmNoYW5nZWQgUHJpY2VzIiwKICAgIHggPSAiVHJhbnNwb3J0IENvc3QiLAogICAgY29sb3IgPSAiUGVyaW9kIE51bWJlciIKICApCgpkZiAlPiUKICBncm91cF9ieShwbGF5ZXIudHJhbnNwb3J0X2Nvc3QpICU+JQogIHN1bW1hcmlzZSgKICAgIG4gPSBuKCksCiAgICBwcmljZV9jaHJfcHJjdF9tZWFuID0gbWVhbihwcmljZV9tZWFuX2NoZyksCiAgICBwcmljZV9jaHJfcHJjdF9tZWRpYW4gPSBtZWRpYW4ocHJpY2VfbWVhbl9jaGcpCiAgICAKICApCmBgYAoKCgotLS0tLS0tLS0tLQoKIyMgUGVyaW9kIEVmZmVjdAoKVGhlIHBlcmlvZCBhZmZlY3QsIGlmIHByZXNlbnQsIGlzIGRvbWluYXRlZCBieSB0cmFuc3BvcnQgY29zdHMgYWxsIGJlaW5nIHRoZSBzYW1lIGF0IGNlcnRhaW4gcGVyaW9kcy4KCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTMuNSwgZmlnLndpZHRoPTh9CmdncGxvdCgKICBzZXNEYXQ0cCAlPiUKICAgIGdyb3VwX2J5KHNlc3Npb24uY29kZSwgcGFydGljaXBhbnQuY29kZSwgcGxheWVyLnRyYW5zcG9ydF9jb3N0LHBsYXllci5wZXJpb2RfbnVtYmVyKSAlPiUgCiAgICBzdW1tYXJpc2UoCiAgICAgIG1lYW5fcHJvZml0ID0gbWVhbihwbGF5ZXIucm91bmRfcGF5b2ZmICogMjApCiAgICApICU+JQogICAgZmlsdGVyKAogICAgICAhaXMubmEobWVhbl9wcm9maXQpLAogICAgICBwbGF5ZXIudHJhbnNwb3J0X2Nvc3QgIT0gMC4yNQogICAgKQopICsKICAgIGdlb21fYm94cGxvdCgKICAgIGFlcygKICAgICAgeCA9IGFzLmZhY3RvcihwbGF5ZXIucGVyaW9kX251bWJlciksCiAgICAgIHkgPSBtZWFuX3Byb2ZpdAogICAgKSwgYWxwaGEgPSAuMwogICkgKwogIGdlb21faml0dGVyKAogICAgYWVzKAogICAgICB4ID0gYXMuZmFjdG9yKHBsYXllci5wZXJpb2RfbnVtYmVyKSwKICAgICAgeSA9IG1lYW5fcHJvZml0CiAgICApLCBhbHBoYSA9IC43CiAgKQpgYGAKCgojIENvbXBhcmluZyB0aGUgdHdvLXBsYXllciBnYW1lIHRvIGZvdXItcGxheWVyCgpGaXJzdCBvZmYgbm90ZSB0aGF0IGluIHRoZSB0d28tcGxheWVyIGdhbWUsIHRoZSBtb3N0IHlvdSBjYW4gcG9zc2libGUgZWFybiBpcyAwLjUuIEluIHRoZSBmb3VyLXBsYXllciBnYW1lIGlmIGFsbCBwbGF5ZXJzIHNldCBwcmljZXMgYXQgdGhlaXIgbWF4IHRoZXkgd291bGQgZWFjaCBlYXJuIDAuMjUuIAoKLS0tCgotLSoqRGF2ZSoqOiBUaGVzZSByZXN1bHRzIGxvb2sgZ3JlYXQuIFNvLCBpdCBsb29rcyBsaWtlIHdlIGhhdmUgcHJldHR5IHJvYnVzdCByZXN1bHRzIGZvciBvbmUgb2Ygb3VyIGh5cG90aGVzZXMgKHRyYW5zcG9ydCBjb3N0cyBhbmQgcHJvZml0cyAobWFyay11cHMpIGZyb20gdGhlc2UgcGlsb3RzLiBUaGUgb3RoZXIgcXVlc3Rpb25zIGFyZSBtb3N0bHkgdG8gZG8gd2l0aCBob3cgdGhlIHJlc3VsdHMgY2hhbmdlIGZvciB0aGUgMnAgdnMuIDRwIGdhbWVzLiBJZiBpdCdzIHJlbGF0aXZlbHkgZWFzeSwgY291bGQgeW91IGdlbmVyYXRlIHRob3NlIHNhbWUgcGxvdHMsIGJ1dCB3aGVyZSB5b3Ugc3RhY2sgdGhlIDJwIGFuZCA0cCBpbWFnZXMgb24gdG9wIG9mIGVhY2ggb3RoZXIgc28gaXQncyBlYXNpZXIgdG8gdmlzdWFsbHkgY29tcGFyZT8gUmlnaHQgbm93IEknbSB0cnlpbmcgdG8gc2Nyb2xsIGJhY2sgYW5kIGZvcnRoIHRvIGNvbXBhcmUgYW5kIGl0J3Mgbm90IHdvcmtpbmcgdG9vIHdlbGwhIC0tCgoKIyMgUGVyaW9kIFByb2ZpdCBhbmQgVHJhbnNwb3J0IENvc3QKCmBgYHtyLCBlY2hvPUZBTFNFfQoKZGYgPSAgc2VzRGF0MnAgJT4lCiAgdW5ncm91cCgpICU+JQogIGdyb3VwX2J5KHNlc3Npb24uY29kZSwgcGFydGljaXBhbnQuY29kZSwgcGxheWVyLnRyYW5zcG9ydF9jb3N0LHBsYXllci5wZXJpb2RfbnVtYmVyKSAlPiUKICBtdXRhdGUoCiAgICBwbGF5ZXIucm91bmRfcGF5b2ZmID0gcGxheWVyLnJvdW5kX3BheW9mZiAqIG1heChzdWJzZXNzaW9uLnJvdW5kX251bWJlcikgI2RlYWwgd2l0aCBmJ2luZyB0PTAuMjUuLi4KICApICU+JQogICBzdW1tYXJpc2UoCiAgICAgbWVhbl9wcm9maXQgPSBtZWFuKHBsYXllci5yb3VuZF9wYXlvZmYpCiAgICkgJT4lCiAgbXV0YXRlKAogICAgTnVtUGxheWVycyA9ICJ0d28tcGxheWVycyIKICApCgpkZiA9IGJpbmRfcm93cygKICBkZiwgCiAgKCAgc2VzRGF0NHAgJT4lCiAgICAgICBncm91cF9ieShzZXNzaW9uLmNvZGUscGxheWVyLnRyYW5zcG9ydF9jb3N0KSAlPiUKICAgICAgIGdyb3VwX2J5KHNlc3Npb24uY29kZSwgcGFydGljaXBhbnQuY29kZSwgcGxheWVyLnRyYW5zcG9ydF9jb3N0LHBsYXllci5wZXJpb2RfbnVtYmVyKSAlPiUgCiAgICAgICBzdW1tYXJpc2UoCiAgICAgICAgIG1lYW5fcHJvZml0ID0gbWVhbihwbGF5ZXIucm91bmRfcGF5b2ZmICogbWF4KHN1YnNlc3Npb24ucm91bmRfbnVtYmVyKSkKICAgICAgICkgJT4lCiAgICAgICBmaWx0ZXIoCiAgICAgICAgICFpcy5uYShtZWFuX3Byb2ZpdCkKICAgICAgICkgJT4lCiAgICAgICBtdXRhdGUoCiAgICAgICAgIE51bVBsYXllcnMgPSAiZm91ci1wbGF5ZXJzIgogICAgICAgKQogICkKKQoKZGYyID0gZGYgJT4lCiAgZ3JvdXBfYnkoCiAgICBwbGF5ZXIudHJhbnNwb3J0X2Nvc3QsIE51bVBsYXllcnMKICApICU+JQogIHN1bW1hcmlzZSgKICAgIG1lYW5fcHJvZml0ID0gbWVhbihtZWFuX3Byb2ZpdCkKICApCgpnZ3Bsb3QoCiBkZgopICsKICAgIGdlb21fdmlvbGluKAogICAgYWVzKAogICAgICB4ID0gKHBsYXllci50cmFuc3BvcnRfY29zdCksCiAgICAgIHkgPSBtZWFuX3Byb2ZpdCwKICAgICAgZ3JvdXAgPSBwbGF5ZXIudHJhbnNwb3J0X2Nvc3QKICAgICksIGFscGhhID0gLjgKICApICsKICBnZW9tX2ppdHRlcigKICAgIGFlcygKICAgICAgeCA9IChwbGF5ZXIudHJhbnNwb3J0X2Nvc3QpLAogICAgICB5ID0gbWVhbl9wcm9maXQsCiAgICAgIGNvbG9yID0gcGxheWVyLnBlcmlvZF9udW1iZXIKICAgICksIAogICAgYWxwaGEgPSAuMywKICAgIHdpZHRoID0gLjA1LCBoZWlnaHQgPSAwCiAgKSArCiAgZ2VvbV9saW5lKAogICAgZGF0YSA9IGRmMiwKICAgIGFlcygKICAgICAgeSA9IChtZWFuX3Byb2ZpdCksIAogICAgICB4ID0gKHBsYXllci50cmFuc3BvcnRfY29zdCkpCiAgKSArCiAgZmFjZXRfZ3JpZChOdW1QbGF5ZXJzfi4pICsKICB0aGVtZV9idygpCgoKCgpgYGAKCiMjIFByaWNlIFN0YW5kYXJkIERldmlhdGlvbiBhbmQgVHJhbnNwb3J0IENvc3QKCmBgYHtyLCBlY2hvPUZBTFNFfQoKCmRmID0gIHNlc0RhdDJwICU+JQogIHVuZ3JvdXAoKSAlPiUKICBncm91cF9ieShzZXNzaW9uLmNvZGUsIHBhcnRpY2lwYW50LmNvZGUsIHBsYXllci50cmFuc3BvcnRfY29zdCxwbGF5ZXIucGVyaW9kX251bWJlcikgJT4lCiAgbXV0YXRlKAogICAgcGxheWVyLnJvdW5kX3BheW9mZiA9IHBsYXllci5yb3VuZF9wYXlvZmYgKiBtYXgoc3Vic2Vzc2lvbi5yb3VuZF9udW1iZXIpICNkZWFsIHdpdGggZidpbmcgdD0wLjI1Li4uCiAgKSAlPiUKICAgc3VtbWFyaXNlKAogICAgIG1lYW5fcHJpY2UgPSBtZWFuKHBsYXllci5wcmljZSksCiAgICAgcHJpY2Vfc2QgPSBzZChwbGF5ZXIucHJpY2UpCiAgICkgJT4lCiAgbXV0YXRlKAogICAgTnVtUGxheWVycyA9ICJ0d28tcGxheWVycyIKICApCgpkZiA9IGJpbmRfcm93cygKICBkZiwKICBzZXNEYXQ0cCAlPiUKICB1bmdyb3VwKCkgJT4lCiAgZ3JvdXBfYnkoc2Vzc2lvbi5jb2RlLHBhcnRpY2lwYW50LmNvZGUscGxheWVyLnRyYW5zcG9ydF9jb3N0LHBsYXllci5wZXJpb2RfbnVtYmVyKSAlPiUKICAgc3VtbWFyaXNlKAogICAgIG1lYW5fcHJpY2UgPSBtZWFuKHBsYXllci5wcmljZSksCiAgICAgcHJpY2Vfc2QgPSBzZChwbGF5ZXIucHJpY2UpCiAgICkgJT4lCiAgICBtdXRhdGUoTnVtUGxheWVycyA9ICJmb3VyLXBsYXllcnMiKQopIAoKCmdncGxvdCgKIGRmCikgKwogICAgZ2VvbV92aW9saW4oCiAgICBhZXMoCiAgICAgIHggPSBhcy5mYWN0b3IocGxheWVyLnRyYW5zcG9ydF9jb3N0KSwKICAgICAgeSA9IHByaWNlX3NkCiAgICApLCBhbHBoYSA9IC44CiAgKSArCiAgZ2VvbV9qaXR0ZXIoCiAgICBhZXMoCiAgICAgIHggPSBhcy5mYWN0b3IocGxheWVyLnRyYW5zcG9ydF9jb3N0KSwKICAgICAgeSA9IHByaWNlX3NkLAogICAgICBjb2xvciA9IHBsYXllci5wZXJpb2RfbnVtYmVyCiAgICApLCAKICAgIGFscGhhID0gLjMsCiAgICB3aWR0aCA9IC4xLCBoZWlnaHQgPSAwCiAgKSArCiAgZmFjZXRfZ3JpZChOdW1QbGF5ZXJzfi4pICsKICB0aGVtZV9idygpICsKICBsYWJzKAogICAgdGl0bGUgPSAiUHJpY2UgU3RhbmRhcmQgRGV2aWF0aW9uIGFuZCBUcmFuc3BvcnQgQ29zdCIsCiAgICBzdWJ0aXRsZSA9ICJPbmUgZG90IGlzIG9uZSBzdWJqZWN0J3MgcHJpY2Ugc2QgaW4gb25lIHBlcmlvZCwgYXQgdGhpcyB0cmFuc3BvcnQgY29zdC4iLAogICAgeSA9ICJQcmljZSBTdGFuZGFyZCBEZXZpYXRpb24iLAogICAgeCA9ICJUcmFuc3BvcnQgQ29zdCIsCiAgICBjb2xvciA9ICJQZXJpb2QgTnVtYmVyIgogICkgCmBgYAoKIyMgUHJpY2UgU3RpY2tpbmVzcwoKKipEYXZlKio6IE9uIHByaWNlIHN0aWNraW5lc3MuIEkgd2FzIHRoaW5raW5nIG1vcmUgYWxvbmcgdGhlIGxpbmVzIG9mICJwcmljZSByZXNwb25zaXZlbmVzcyIgSSBzdXBwb3NlLiBpLmUuIHRoYXQgcHJpY2UgYXJlIGxlc3MgcmVzcG9uc2l2ZSB0byBzaG9ja3MgKGNoYW5nZXMgaW4gdHJhbnNwb3J0IGNvc3RzKSBpbiB0aGUgMnAgc2Vzc2lvbnMuIFdlIGNvdWxkIHJ1biB0aGUgc2FtZSByZWdyZXNzaW9uIGFib3ZlLCBidXQgd2l0aCBwcmljZSwgYnV0IEkgdGhpbmsgd2Ugc2hvdWxkIGdldCB0aGUgc2FtZSByZXN1bHQsIHNpbmNlIHByb2ZpdCBlc3NlbnRpYWxseSBlcXVhbHMgcHJpY2UgaGVyZSAobm90IGV4YWN0bHksIG9mIGNvdXJzZSkuIFRoaXMgaXMgcmVsYXRlZCB0byBwcmljZSBzdGlja2luZXNzIGJlY2F1c2UgaWYgcHJpY2VzIGFyZSBsZXNzIHJlc3BvbnNpdmUsIGZvciB3aGF0ZXZlciByZWFzb24sIG1vbmV0YXJ5IHBvbGljeSB3aWxsIGhhdmUgYSBncmVhdGVyIGltcGFjdC4gSSBndWVzcyBJJ20gbGVzcyBpbnRlcmVzdGVkIGluIHRoZSB3aXRoaW4gcm91bmQgbW92ZW1lbnRzIGluIHByaWNlLCBJIGp1c3Qgc29ydCBvZiB2aWV3IHRoYXQgYXMgZXhwZXJpbWVudGF0aW9uLiBPbmUgdGhpbmcgdGhhdCBJIHRoaW5rIG1heSBiZSBpbnRlcmVzdGluZyBpcyB0byBsb29rIGF0IGhvdyBwcmljZSBjaGFuZ2VzIGNoYW5nZSBhcyByb3VuZHMgZ28gb24uIGkuZS4gZG8gdGhlIGNoYW5nZXMgYmVjb21lIGxlc3MgZXh0cmVtZSBsYXRlciBpbiBhIHBlcmlvZCBhbmQgZG9lcyB0aGlzIHZhcnkgYWNyb3NzIHRyYW5zcG9ydCBjb3N0cy4gQWdhaW4sIHRoZSBtZXRyaWNzIG9uIHByaWNlIHN0aWNraW5lc3MgeW91IGNyZWF0ZSBhbmQgdGhpbmsgYXJlIGludGVyZXN0aW5nLCBidXQgY291bGQgeW91IGRvIHRoZW0gZm9yIGEgMnAgdnMuIDRwIGNvbXBhcmlzb24/IEkgdGhpbmsgdGhhdCBjb21wYXJpc29uIGlzIG11Y2ggbW9yZSBpbnRlcmVzdGluZy4gSSB0aGluayB3ZSBzaG91bGQga2VlcCB0aGUgdHJhbnNwb3J0IGNvc3Qgb25lcywgYnV0IEknZCBhbHNvIGxpa2UgdG8gYWRkIHRoZSAycCB2cy4gNHAgY29tcGFyaXNvbi4KCmBgYHtyLCBlY2hvPUZBTFNFfQoKZGYgPSAgc2VzRGF0MnAgJT4lCiAgdW5ncm91cCgpICU+JQogIGdyb3VwX2J5KHNlc3Npb24uY29kZSwgcGFydGljaXBhbnQuY29kZSwgcGxheWVyLnRyYW5zcG9ydF9jb3N0LHBsYXllci5wZXJpb2RfbnVtYmVyKSAlPiUKICBzdW1tYXJpc2UoCiAgICBwcmljZSA9IG1lYW4ocGxheWVyLnByaWNlKSwKICAgIHByaWNlX21lZGlhbiA9IG1lZGlhbihwbGF5ZXIucHJpY2UpLAogICAgdHdvUGxheWVyID0gMSwKICAgIHBsYXllck51bSA9ICJUd28gUGxheWVycyIKICApCgpkZiA9IGJpbmRfcm93cygKICBkZiwgCiAgc2VzRGF0NHAgJT4lCiAgICB1bmdyb3VwKCkgJT4lCiAgICBncm91cF9ieShzZXNzaW9uLmNvZGUsIHBhcnRpY2lwYW50LmNvZGUsIHBsYXllci50cmFuc3BvcnRfY29zdCxwbGF5ZXIucGVyaW9kX251bWJlcikgJT4lCiAgICBzdW1tYXJpc2UoCiAgICBwcmljZSA9IG1lYW4ocGxheWVyLnByaWNlKSwKICAgIHByaWNlX21lZGlhbiA9IG1lZGlhbihwbGF5ZXIucHJpY2UpLAogICAgICB0d29QbGF5ZXIgPSAwLAogICAgICBwbGF5ZXJOdW0gPSAiRm91ciBQbGF5ZXJzIgogICAgKQopICU+JQogIGRwbHlyOjpmaWx0ZXIoCiAgICBwbGF5ZXIudHJhbnNwb3J0X2Nvc3QgIT0gMC4yNQogICkgJT4lCiAgZ3JvdXBfYnkocGxheWVyTnVtKSAlPiUKICBkcGx5cjo6bXV0YXRlKAogICAgc2RfcHJpY2UgPSBzZChwcmljZSksCiAgICBzdGR6X3ByaWNlID0gcHJpY2UgLyBzZF9wcmljZQogICkKCgoKcDE9IGdncGxvdCgKICBkZiwKICBhZXMoCiAgICB4ID0gcGxheWVyLnRyYW5zcG9ydF9jb3N0LAogICAgeSA9IGxvZyhwcmljZSksCiAgICBncm91cCA9IHBsYXllck51bSwKICAgIGNvbG9yID0gcGxheWVyTnVtCiAgKQopICsKICBnZW9tX2ppdHRlcigKICAgIHdpZHRoID0gMC4wNywKICAgIGFscGhhID0gLjQpICsKICBnZW9tX3Ntb290aCgKICAgIG1ldGhvZCA9ICdsbScKICApICsKICB0aGVtZV9idygpCnAxCgoKCnJlZyA9IGxtKAogIGxvZyhwcmljZSkgfiBsb2cocGxheWVyLnRyYW5zcG9ydF9jb3N0KSArIHR3b1BsYXllciArIHR3b1BsYXllcjpsb2cocGxheWVyLnRyYW5zcG9ydF9jb3N0KSwKICBkZgopCgpzdW1tYXJ5KHJlZykKYGBgCgpTaW1pbGFyIHJlc3VsdHMgdG8gbG9nLWxvZyB3aXRoIHByb2ZpdCBhbmQgdHJhbnNwb3J0IGNvc3RzLiAKCgpBbmQgd2l0aCBub3JtYWxpemVkIHByaWNlLCAKCmBgYHtyLCBlY2hvPUZBTFNFfQpyZWcgPSBsbSgKICBzdGR6X3ByaWNlIH4gbG9nKHBsYXllci50cmFuc3BvcnRfY29zdCkgKyB0d29QbGF5ZXIgKyB0d29QbGF5ZXI6bG9nKHBsYXllci50cmFuc3BvcnRfY29zdCksCiAgZGYKKQoKc3VtbWFyeShyZWcpCmBgYAoKVGhlIHJlc3VsdHMgaXMgbm93IGluc2lnbmlmaWNhbnQuIAoKCi0tLQoKCiMjIFN1c3RhaW5lZCBqb2ludCBwcm9maXRzLiAKCkFzIGEgbWVhc3VyZSBvciBpbmRpY2F0aW9uIG9mIGNvbGx1c2lvbiwgaGVyZSB3ZSB1c2UgdGhlIHNpdHVhdGlvbiBpbiB3aGljaCBib3RoIHBsYXllcnMgaGF2ZSBwcm9maXRhYmxlIHBvc2l0aW9ucy4KClRoZXJlIGFyZSBvdGhlciBleHBsYWluYXRpb25zIGZvciBib3RoIHBsYXllcnMgaGF2aW5nIHBvc2l0aXZlIHByb2ZpdHMgd2hlcmUgdGhleSBhcmUgbm90IGNvbGx1ZGluZy4gRm9yIGV4YW1wbGUsIGlmIHRoZXkgYXJlIGF0dGVtcHRpbmcgdG8gdW5kZXJjdXQgdGhlaXIgY29tcGV0aXRvciBidXQgYWNjaWRlbnRpYWxseSBhbGxvdyB0aGVtIGEgcHJvZml0LiBIaWdoIHRyYW5zcG9ydCBjb3N0cyBhbHNvIGxpbWl0IHRoZSBhYmlsaXR5IGZvciBjb21wZXRpdG9ycyB0byB1bmRlcmN1dCBvdGhlcnMuIAoKVGhlIGZvbGxvd2luZyB0YWJsZSBzaG93cyB0aGUgcGVyY2VudCBvZiB0aGUgc3VicGVyaW9kIGluIHdoaWNoIGFsbCBwbGF5ZXJzIGhhZCBhdCBwb3NpdGl2ZSBwYXlvZmZzLiBXZSAgc2VlIGEgY2xlYXIgcmVsYXRpb25zaGlwIGJldHdlZW4gdHJhbnNwb3J0IGNvc3QgYW5kIGZpcm1zIGFiaWxpdHkgdG8gbWFpbnRhaW4gam9pbnQgcG9zaXRpdmUgcHJvZml0cy4gCgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLmhlaWdodD0zLjUsIGZpZy53aWR0aD04fQoKIyAyIHBsYXllcgoKZGYgPSBmdWxsX2pvaW4oCiAgc2VzRGF0MnAgJT4lCiAgdW5ncm91cCgpICU+JQogIGFycmFuZ2Uoc2Vzc2lvbi5jb2RlLCBncm91cC5pZF9pbl9zdWJzZXNzaW9uLCBwbGF5ZXIucGVyaW9kX251bWJlciwgc3Vic2Vzc2lvbi5yb3VuZF9udW1iZXIpICU+JQogIGdyb3VwX2J5KHNlc3Npb24uY29kZSwgcGxheWVyLnBlcmlvZF9udW1iZXIpICU+JQogIG11dGF0ZSgKICAgIG1heF9yb3VuZG51bWJlciA9IG1heChzdWJzZXNzaW9uLnJvdW5kX251bWJlciksCiAgICBwYXlvZmYgPSBwbGF5ZXIucm91bmRfcGF5b2ZmICogbWF4KHN1YnNlc3Npb24ucm91bmRfbnVtYmVyKQogICkgJT4lCiAgc2VsZWN0KAogICAgc2Vzc2lvbi5jb2RlLCBncm91cC5pZF9pbl9zdWJzZXNzaW9uLCAKICAgIHBsYXllci5wZXJpb2RfbnVtYmVyLCBzdWJzZXNzaW9uLnJvdW5kX251bWJlciwgcGxheWVyLnRyYW5zcG9ydF9jb3N0LAogICAgcGxheWVyLmxvYywgcGxheWVyLnByaWNlCiAgKSAlPiUKICBtdXRhdGUoCiAgICBwbGF5ZXIubG9jID0gcGFzdGUoInByaWNlXyIscGxheWVyLmxvYywgc2VwPSIiKQogICkgJT4lCiAgc3ByZWFkKHBsYXllci5sb2MsIHBsYXllci5wcmljZSksCiAgc2VzRGF0MnAgJT4lCiAgdW5ncm91cCgpICU+JQogIGFycmFuZ2Uoc2Vzc2lvbi5jb2RlLCBncm91cC5pZF9pbl9zdWJzZXNzaW9uLCBwbGF5ZXIucGVyaW9kX251bWJlciwgc3Vic2Vzc2lvbi5yb3VuZF9udW1iZXIpICU+JQogIGdyb3VwX2J5KHNlc3Npb24uY29kZSwgcGxheWVyLnBlcmlvZF9udW1iZXIpICU+JQogIG11dGF0ZSgKICAgIG1heF9yb3VuZG51bWJlciA9IG1heChzdWJzZXNzaW9uLnJvdW5kX251bWJlciksCiAgICBwYXlvZmYgPSBwbGF5ZXIucm91bmRfcGF5b2ZmICogbWF4KHN1YnNlc3Npb24ucm91bmRfbnVtYmVyKQogICkgJT4lCiAgc2VsZWN0KAogICAgc2Vzc2lvbi5jb2RlLCBncm91cC5pZF9pbl9zdWJzZXNzaW9uLCAKICAgIHBsYXllci5wZXJpb2RfbnVtYmVyLCBzdWJzZXNzaW9uLnJvdW5kX251bWJlciwgcGxheWVyLnRyYW5zcG9ydF9jb3N0LAogICAgcGxheWVyLmxvYywgcGF5b2ZmCiAgKSAlPiUKICBtdXRhdGUoCiAgICBwbGF5ZXIubG9jID0gcGFzdGUoInBheW9mZl8iLHBsYXllci5sb2MsIHNlcD0iIikKICApICU+JQogIHNwcmVhZChwbGF5ZXIubG9jLCBwYXlvZmYpLAogIGJ5ID0gYygic2Vzc2lvbi5jb2RlIiwgImdyb3VwLmlkX2luX3N1YnNlc3Npb24iLCAicGxheWVyLnBlcmlvZF9udW1iZXIiLCAic3Vic2Vzc2lvbi5yb3VuZF9udW1iZXIiLCAicGxheWVyLnRyYW5zcG9ydF9jb3N0IikKKQoKZGYgPSBkZiAlPiUKICB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKAogICAgcGF5b2ZmX2RpZmYgPSBhYnMocGF5b2ZmXzAuNzUgLSBwYXlvZmZfMC4yNSksCiAgICBwYXlvZmZfYm90aHBvcyA9IGlmZWxzZShwYXlvZmZfMC43NSA9PSAwIHwgcGF5b2ZmXzAuMjUgPT0gMCwgRkFMU0UsIFRSVUUpCiAgKQoKZGZfMnAgPSBkZiAlPiUKICBncm91cF9ieShwbGF5ZXIudHJhbnNwb3J0X2Nvc3QpICU+JQogIHN1bW1hcml6ZSgKICAgIG1lYW5fam9pbnRQb3NQcm9maXRzID0gbWVhbihwYXlvZmZfYm90aHBvcykKICApICU+JQogIG11dGF0ZSgKICAgIHBsYXllcnMgPSAyCiAgKSAlPiUKICBzZWxlY3QocGxheWVyLnRyYW5zcG9ydF9jb3N0LCBwbGF5ZXJzLCBtZWFuX2pvaW50UG9zUHJvZml0cykKCiMgZm91ciBwbGF5ZXIKZGYgPSBmdWxsX2pvaW4oCiAgc2VzRGF0NHAgJT4lCiAgdW5ncm91cCgpICU+JQogIGFycmFuZ2Uoc2Vzc2lvbi5jb2RlLCBncm91cC5pZF9pbl9zdWJzZXNzaW9uLCBwbGF5ZXIucGVyaW9kX251bWJlciwgc3Vic2Vzc2lvbi5yb3VuZF9udW1iZXIpICU+JQogIGdyb3VwX2J5KHNlc3Npb24uY29kZSwgcGxheWVyLnBlcmlvZF9udW1iZXIpICU+JQogIG11dGF0ZSgKICAgIG1heF9yb3VuZG51bWJlciA9IG1heChzdWJzZXNzaW9uLnJvdW5kX251bWJlciksCiAgICBwYXlvZmYgPSBwbGF5ZXIucm91bmRfcGF5b2ZmICogbWF4KHN1YnNlc3Npb24ucm91bmRfbnVtYmVyKQogICkgJT4lCiAgc2VsZWN0KAogICAgc2Vzc2lvbi5jb2RlLCBncm91cC5pZF9pbl9zdWJzZXNzaW9uLCAKICAgIHBsYXllci5wZXJpb2RfbnVtYmVyLCBzdWJzZXNzaW9uLnJvdW5kX251bWJlciwgcGxheWVyLnRyYW5zcG9ydF9jb3N0LAogICAgcGxheWVyLmxvYywgcGxheWVyLnByaWNlCiAgKSAlPiUKICBtdXRhdGUoCiAgICBwbGF5ZXIubG9jID0gcGFzdGUoInByaWNlXyIscGxheWVyLmxvYywgc2VwPSIiKQogICkgJT4lCiAgc3ByZWFkKHBsYXllci5sb2MsIHBsYXllci5wcmljZSksCiAgc2VzRGF0NHAgJT4lCiAgdW5ncm91cCgpICU+JQogIGFycmFuZ2Uoc2Vzc2lvbi5jb2RlLCBncm91cC5pZF9pbl9zdWJzZXNzaW9uLCBwbGF5ZXIucGVyaW9kX251bWJlciwgc3Vic2Vzc2lvbi5yb3VuZF9udW1iZXIpICU+JQogIGdyb3VwX2J5KHNlc3Npb24uY29kZSwgcGxheWVyLnBlcmlvZF9udW1iZXIpICU+JQogIG11dGF0ZSgKICAgIG1heF9yb3VuZG51bWJlciA9IG1heChzdWJzZXNzaW9uLnJvdW5kX251bWJlciksCiAgICBwYXlvZmYgPSBwbGF5ZXIucm91bmRfcGF5b2ZmICogbWF4KHN1YnNlc3Npb24ucm91bmRfbnVtYmVyKQogICkgJT4lCiAgc2VsZWN0KAogICAgc2Vzc2lvbi5jb2RlLCBncm91cC5pZF9pbl9zdWJzZXNzaW9uLCAKICAgIHBsYXllci5wZXJpb2RfbnVtYmVyLCBzdWJzZXNzaW9uLnJvdW5kX251bWJlciwgcGxheWVyLnRyYW5zcG9ydF9jb3N0LAogICAgcGxheWVyLmxvYywgcGF5b2ZmCiAgKSAlPiUKICBtdXRhdGUoCiAgICBwbGF5ZXIubG9jID0gcGFzdGUoInBheW9mZl8iLHBsYXllci5sb2MsIHNlcD0iIikKICApICU+JQogIHNwcmVhZChwbGF5ZXIubG9jLCBwYXlvZmYpLAogIGJ5ID0gYygic2Vzc2lvbi5jb2RlIiwgImdyb3VwLmlkX2luX3N1YnNlc3Npb24iLCAicGxheWVyLnBlcmlvZF9udW1iZXIiLCAic3Vic2Vzc2lvbi5yb3VuZF9udW1iZXIiLCAicGxheWVyLnRyYW5zcG9ydF9jb3N0IikKKQoKZGYgPSBkZiAlPiUKICB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKAogICAgcGF5b2ZmX2JvdGhwb3MgPSBpZmVsc2UocGF5b2ZmXzAuMTI1ID09IDAgfHBheW9mZl8wLjM3NSA9PSAwIHxwYXlvZmZfMC42MjUgPT0gMCB8IHBheW9mZl8wLjg3NSA9PSAwLCBGQUxTRSwgVFJVRSkKICApCgpkZl80cCA9IGRmICU+JQogIGdyb3VwX2J5KHBsYXllci50cmFuc3BvcnRfY29zdCkgJT4lCiAgc3VtbWFyaXplKAogICAgbWVhbl9qb2ludFBvc1Byb2ZpdHMgPSBtZWFuKHBheW9mZl9ib3RocG9zKQogICkgJT4lCiAgbXV0YXRlKAogICAgcGxheWVycyA9IDQKICApICU+JQogIHNlbGVjdChwbGF5ZXIudHJhbnNwb3J0X2Nvc3QsIHBsYXllcnMsIG1lYW5fam9pbnRQb3NQcm9maXRzKQoKCmRmID0gYmluZF9yb3dzKGRmXzRwLCBkZl8ycCkKCmthYmxlKAogIGZvcm1hdCA9ICJtYXJrZG93biIsIAogIGRmLCAgYWxpZ24gPSBjKCJjIikKICAjIGNvbC5uYW1lcyA9IGMoIiIsIiIsIiIsIkF2ZyBUYXNrIDEgUkVUIFNjb3JlIiwiQXZnIFRhc2sgMiBSRVQgU2NvcmUiLCJBdmcgVGFzayAzIFJFVCBTY29yZSIsIlRvdXJuIiwgIlNzIikKKQoKYGBgCgpCZWxvdywgSSBhbSBjdXJpb3VzIGhvdyBwYXlvZmZzIGV2b2x2ZWQgYXMgcGVyaW9kcyBwcm9ncmVzc2VkLiBXZXJlIHRoZXkgc3RhYmxlLCBvciBkaWQgdGhleSB0ZW5kIHRvIGRlY2xpbmU/IAoKVGhlIHBsb3RzIGJlbG93IHNob3cgdGhlIGRpc3RyaWJ1dGlvbnMgb2YgcGF5b2ZmcyBvdmVyIHRoZSBwZXJpb2QuIFRoZSB4LWF4aXMgaXMgdGhlIHN1YnBlcmlvZCwgdGhlIHktYXhpcyB0aGUgZmxvdyBwYXlvZmYuIAoKVGhlcmUgYXJlIGppdHRlcmVkIHBvaXRzIGFuZCB2aW9saW5zIHRvIHNob3cgZGlzdHJpYnV0aW9ucy4gVGhlIGxpbmUgc2hvd3MgdGhlIG1lZGlhbiBvdmVyIGFsbCBvYnNlcnZhdGlvbnMgaW4gdGhpcyBncm91cC4gCgpJdCdzIGhhcmQgdG8gc2VlLCBidXQgaW4gdGhlIHR3by1wbGF5ZXIgZ2FtZSwgdGhlIGRpc3RyaWJ1dGlvbnMgb2YgcHJvZml0cyBhcmUgcmVtYXJrYWJseSBjb25zaXN0ZW50IGJldHdlZW4gc3VicGVyaW9kcyBpbiBgdCA9IDAuNSwgMC43NSBhbmQgMS4wYC4KCgoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9NSwgZmlnLndpZHRoPTh9CgpnZ3Bsb3QoCiAgYmluZF9yb3dzKAogICAgc2VzRGF0MnAgJT4lIG11dGF0ZShwbGF5ZXIgPSAiMnBsYXllciIpLCAKICAgIHNlc0RhdDRwICU+JSBtdXRhdGUocGxheWVyID0gIjRwbGF5ZXIiKQogICkgJT4lCiAgICBncm91cF9ieShwbGF5ZXIudHJhbnNwb3J0X2Nvc3QsIHNlc3Npb24uY29kZSwgcGxheWVyLnBlcmlvZF9udW1iZXIpICU+JQogICAgbXV0YXRlKAogICAgICBwYXlvZmYgPSBpZmVsc2UoCiAgICAgICAgcGxheWVyID09ICI0cGxheWVyIiwKICAgICAgICBwbGF5ZXIucm91bmRfcGF5b2ZmICogMjAsCiAgICAgICAgcGxheWVyLmN1bXVsYXRpdmVfcm91bmRfcGF5b2ZmKQogICAgKSwKICBhZXMoCiAgICB4ID0gc3Vic2Vzc2lvbi5yb3VuZF9udW1iZXIsIAogICAgeSA9IHBheW9mZgogICkKKSArCiAgZ2VvbV92aW9saW4oYWVzKGdyb3VwID0gc3Vic2Vzc2lvbi5yb3VuZF9udW1iZXIpKSArCiAgZ2VvbV9qaXR0ZXIoYWxwaGEgPSAwLjEpICsKICBnZW9tX2xpbmUoCiAgICBkYXRhID0gICBiaW5kX3Jvd3MoCiAgICBzZXNEYXQycCAlPiUgbXV0YXRlKHBsYXllciA9ICIycGxheWVyIiksIAogICAgc2VzRGF0NHAgJT4lIG11dGF0ZShwbGF5ZXIgPSAiNHBsYXllciIpCiAgKSAlPiUKICAgIGdyb3VwX2J5KHBsYXllci50cmFuc3BvcnRfY29zdCwgcGxheWVyLHN1YnNlc3Npb24ucm91bmRfbnVtYmVyKSAlPiUKICAgIG11dGF0ZSgKICAgICAgcGF5b2ZmID0gaWZlbHNlKAogICAgICAgIHBsYXllciA9PSAiNHBsYXllciIsCiAgICAgICAgcGxheWVyLnJvdW5kX3BheW9mZiAqIDIwLAogICAgICAgIHBsYXllci5jdW11bGF0aXZlX3JvdW5kX3BheW9mZikKICAgICkgJT4lCiAgICBzdW1tYXJpc2UocGF5b2ZmX21lYW4gPSBtZWRpYW4ocGF5b2ZmKSksCiAgYWVzKHkgPSBwYXlvZmZfbWVhbikpICsKICBmYWNldF9ncmlkKCBwbGF5ZXIgfiBwbGF5ZXIudHJhbnNwb3J0X2Nvc3QpICsKICB0aGVtZV9idygpCgoKIyBkZiA9IGJpbmRfcm93cyhkZl80cCwgZGZfMnApCgoKYGBgCgojIyBEaXN0cmlidXRpb24gb2YgcHJpY2UgY2hhbmdlcy4gCgpPbmUgaW5kaWNhdGlvbiBvZiBjb2xsdXNpb24gaXMgc3RhYmxlIGFjdGlvbnMuIAoKCgoKCgoKCgoKLS0tLSAKCipUaGlzIGlzIGFuIFtSIE1hcmtkb3duXShodHRwOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tKSBOb3RlYm9vay4gV2hlbiB5b3UgZXhlY3V0ZSBjb2RlIHdpdGhpbiB0aGUgbm90ZWJvb2ssIHRoZSByZXN1bHRzIGFwcGVhciBiZW5lYXRoIHRoZSBjb2RlLioKCmBgYHtyLCBlY2hvPUYsIHJlc3VsdHM9J2FzaXMnfQoKY2F0KAogICIgQ29tcGlsZWQgYnkgQ3VydGlzIEtlcGhhcnQsIGN1cnRpcy5rZXBoYXJ0QG55dS5lZHUsICIsCiAgYXMuY2hhcmFjdGVyKFN5cy50aW1lKCkpLCIgR01ULCAiLAogIFN5cy50aW1lem9uZShsb2NhdGlvbiA9IFRSVUUpLAogIHNlcCA9ICIiCikKYGBg